4 ms·
I usually keeping these things as indexed meshes: std::vector<Vector3> for positions, and std::vector<std::array<uint32_t,3>> for the triangles. As a nice side
by Const-me 4y ago
I usually keeping these things as indexed meshes: std::vector<Vector3> for positions, and std::vector<std::array<uint32_t,3>> for the triangles. As a nice side effect, the representation is compatible with GPUs, matches VRAM layout of the vertex/index buffers.
For some simple algorithms which need adjacency information, that’s everything needed. For instance, to compute per-vertex normals, nothing else is required, create an std::vector for the per-vertex accumulators, and iterate over the triangles.
For complicated algorithms which need adjacency information, I build special indices over the same data. To find triangles connected to specific triangle, a hash map with uint64_t keys (two sorted uint32_t vertex IDs in the lower/upper half of the integer) and a structure of two uint32_t values (triangle IDs, good meshes are guaranteed to have exactly 2 triangles for each edge, with opposite winding directions). To find triangles by vertex, a multimap from uint32_t vertex to uint32_t triangle.
For algorithms which need to modify these meshes, sometimes I generate new meshes instead of modifying old ones. Other times I replace erased elements with special values (like UINT_MAX for integer indices), append new elements to the end of the vectors, and when the algorithm is complete I re-index the mesh while removing unused vertices/triangles.