~zjm/Moon3D

0b48eefb50855d9890edc2797bff6b501e998f13 — Zack Michener a month ago 844b23d
add doc explaining rendering meshes
1 files changed, 70 insertions(+), 0 deletions(-)

A Rendering Meshes.md
A Rendering Meshes.md => Rendering Meshes.md +70 -0
@@ 0,0 1,70 @@
Rendering Meshes

For efficient rendering, vertices and vIndexes are stored in object pools. A
pool is just a preallocated array of things, prepended with an int that keeps
track of the number of things in the array. Allocation is fast by returning a
pointer to the next blank slot and incrementing the counter, and draining is
fast by simply setting the counter to zero. A renderer or renderable keeps track
of these pools.

```
Renderable {
  Vertex *vertex_pool;
  int *polygon_pool;
  /* ... */
}

Renderer {
  Vertex *vertex_pool;
  int *polygon_pool;
  /* ... */
}
```

A mesh is a collection of vertices and polygons that define faces of an object.
It keeps track of a contiguous number of vertices in the vertex pool, and a
contiguous number of polygons in the polygon pool (by tracking the address of
the first and the number of vertices/polygons).

```
Mesh {
  int numVertices;
  Vertex *vertices;
  int numPolygons;
  int *polygons;
}
```

A polygon is a list of indices into a vertex array that define the corners of
the polygon. The list is prepended with the number of vertices. The vertex array
is usually the contiguous region of vertices pointed to by a mesh. Polygons are
stored contiguously in the renderer's polygon pool.

```
typedef int *polygon;
```

Because mesh vertices are contiguous regions in the vertex pool, it is
impossible to add new vertices to any except the last mesh. Likewise, it is
impossible to add new faces, or to add new vertices to any face, to any except
the last mesh (and the mesh's last polygon, respectively). However, since we
render an entire mesh at once, we can drain the object pools between each.

A renderable is a persistent model of an object in threespace. When we render a
mesh, we don't want to destroy the original model, so we use temporary pools for
vertices and polygons we want to transform in the renderer.

Rendering a mesh follows this process:

1. Copy and transform all of the mesh's vertices into the renderable pool. A
   modeling transformation and perpective projection is done in this step.
2. Copy and clip all of the mesh's faces into the renderable pool. This may add
   new vertices and v-indices, or remove v-indices. A backface-cull check is done
   to avoid unnecessary copying and clipping.
3. Divide each vertex by W and map into device coordinates.
4. Rasterize or wireframe each polygon.

Because vertices and polygons are contiguous in memory and processed all at
once, this algorithm should be cache-efficient. Because only one copy of a
mesh's data is made and continuously updated, it should be space-efficient. Time
efficienty depends on optimization of each step.