pioneerspacesim/pioneer — pull request #1098 by robn (2012-03-23 08:47:53+00:00)
Title: LMR refactor

Work in progress - not for merge. Posting now because I'm getting stuck and need some fresh eyes on it.

**Broad goals**

* Split LMR into discrete components to make it easier to work with.
* Get LMR to use Renderer for its drawing.
* Decouple the Lua compiler from the geometry builder/accumulator and the renderer proper (as much as possible anyway).

If possible, I'm trying to not change any model scripts. That might be naive, and I will if I have to, but I'd like to do things like remove material and lighting changes later.

**Planned structure**

Incomplete. Names may change.

* `Model` contains multiple `GeomBuffer`s - one per LOD, for static and dynamic, so eight total.
* `GeomBuffer` contains a `StaticMesh` and a set of billboards (no discrete type yet).
* `GeomBuffer` supplies methods for adding triangles to surfaces, changing materials and adding billboards. Triangles and materials get added to `Surface`s, which get added to the final `StaticMesh`.
* `GeomBuffer` also has a method to render itself, which mostly just calls out to the renderer for the mesh and the billboards.
* The `Primitives` namespace holds functions to produce various kinds of meshes - cylinders, lathes, and so on - all the cleverness that the compiler can do.
* `ObjectLoader` knows how to load Wavefront objects and convert them into `GeomBuffer` calls.
* `Compiler` provides the Lua wrappers around `Primitives` and `GeomBuffer`.

Still up in the air is how the dynamic section works. I'm leaning towards having a variant of `GeomBuffer` that has a pointer to a C++ function that will rebuild the geometry, and then a subclass that bridges that into Lua. The theory being that you could produce a dynamic model backed by C++ instead of Lua.

**Progress**

So far I've split a good chunk of stuff out into separate files. `GeomBuffer` is where most of the work is being done. Billboards are working (they were already using the renderer), and the basic structure for surface/mesh construction is there to some extent.

There are some immediate problems that I pretty desperately need help with. They're down at the bottom.

**Open issues**

This is just so far - if course there's going to be more. Input very welcome.

* Currently a typical primitive allocates space for vertices, adds them by direct index, and then adds indicies. `VertexArray` only has an `Add` method (really a push), and I think I'd like to keep it that way. To do that the primitives will need to just push complete triangles, and a post-builld step will need to filter duplicate vertices and optimise the indices for draw. This is probably a good thing to do anyway for good performance (see eg [Tom Forsyth's "Linear-Speed Vertex Cache Optimisation](http://home.comcast.net/~tom_forsyth/papers/fast_vert_cache_opt.html). For the moment I've hacked `GeomBuffer::SetVertex` to continue doing what it always has.
* Z-bias and lights need to be made into material parameters temporarily. In the future we'd like to get rid of z-bias completely and something will have to be done for lights anyway. For the moment though we're trying not to break existing behaviour.
* Dynamic geometry is currently disabled. That's partly because I haven't yet written anything to clear out a `GeomBuffer`'s geometry, but that's not hard. The main thing is that `Renderer` currently wants to put every mesh into a VBO, which obviously isn't the best thing in this case. We probably want a `DynamicMesh` to complement `StaticMesh` (likely with a common `Mesh` subclass). Whether that's completely unbuffered or uses `GL_DYNAMIC_DRAW` buffers I don't know.
* `Material` needs another texture parameter. Easy to do, but I don't know if there then needs to be a "default" multitexturing in the renderer. Probably not.
* There's hacks in the renderer to support LMR. I haven't quite looked into them, but it would be good to remove them.

**Immediate problems**

I need help with these.

The first thing I noticed is that something isn't right with some surfaces. Mostly its a single vertex off the screen somewhere, causing a nice spike across the screen. Intuitively it seems like I'm not closing a surface properly, but I can't see why. I thought that introducing textures and materials would help me to see it, but that really just shows how horrible things are - whole surfaces appear untextured, textures show on the wrong side of a surface, and so on.

I've been testing with `eagle_lrf`, `viper` and `big_crappy_spacestation` in the modelviewer. The game is mostly useless because I've disabled collision mesh generation, which is required for bounding box stuff, which the game needs. Run it anyway, you'll pretty quickly see what's up.