Computational Geometry Graham Rhodes Senior Software Developer, Applied Research Associates, Inc.
What is Computational Geometry? ● Manipulation and interrogation of shapes ● Examples: ● “What is the intersection of a line and a triangle mesh” ● “What is the minimum distance separating two objects” ● “Break a mesh into pieces”
Typical Application in Games ● Interrogation of Geometry ● Collision detection for physics ● Proximity triggers for game logic ● Pathfinding, visibility, and other AI operations ● Manipulation of geometry ● Creation of game assets in 3ds max/Maya/etc ● User-generated content (e.g., Little Big Planet) ● Destruction (Bad Company 2, etc., etc.)
Some Perspective ● Game levels are usually made of meshes ● Typically made of triangles ● Indexed triangle meshes Z Y X
Some Perspective ● Game levels are usually made of meshes 0 <-.5, 0, 0> ● Typically made of triangles 1 <0, 0, 0> ● Indexed triangle meshes 2 <-.5, 0, .5> 3 <0, 0, .5> 9 4 4 <-.25, 0, 1> 8 5 <-.5, 1, 0> 2 6 <0, 1, 0> 3 6 7 <-.5, 1, .5> 0 8 <0, 1, .5> 1 9 <-.25, 1, 1>
Some Perspective ● Game levels are usually made of meshes Triangle Indices ● Typically made of triangles 0, 1, 2 ● Indexed triangle meshes 1, 3, 2 2, 3, 4 9 4 0 <-.5, 0, 0> 1, 6, 3 1 <0, 0, 0> 8 2 <-.5, 0, .5> 3, 6, 8 3 <0, 0, .5> 2 3, 8, 9 3 4 <-.25, 0, 1> 6 5 <-.5, 1, 0> 3, 9, 4 6 <0, 1, 0> 0 7 <-.5, 1, .5> … 1 8 <0, 1, .5> 9 <-.25, 1, 1>
Some Perspective ● Game levels are usually made of meshes Triangle Indices ● Typically made of triangles 0, 1, 2 ● Indexed triangle meshes 1, 3, 2 2, 3, 4 9 4 0 <-.5, 0, 0> 1, 6, 3 1 <0, 0, 0> 8 2 <-.5, 0, .5> 3, 6, 8 3 <0, 0, .5> 2 3, 8, 9 3 4 <-.25, 0, 1> 6 5 <-.5, 1, 0> 3, 9, 4 6 <0, 1, 0> 0 7 <-.5, 1, .5> … 1 8 <0, 1, .5> 9 <-.25, 1, 1>
Getting Ready Computational geometry requires appropriate data structures
Categories of Data Structures ● Spatial ● Find things fast ● BSP tree, octree, Kd-tree, spatial hashing ● Etc… ● Geometry + topology ● Change the shape of objects ● Focus of this talk!
A Computational Geometry Problem ● We have polygons in our game level ● The graphics card requires triangles ● Triangulation converts polygons into triangles How?
The Polygon Triangulation Problem ● Intuitive approach: ear-clipping ● Fast approach: monotone decomposition ● Both involve chopping triangles off in a sequence 1 Polygon Indices 6 6,1,3,0,4,2,5 Number of Polygons: 3 1 0 2 5 4
The Polygon Triangulation Problem ● Intuitive approach: ear-clipping ● Fast approach: monotone decomposition ● Both involve chopping triangles off in a sequence 1 Polygon Indices 6 6,1,3,4,2,5 Number of Polygons: 3 2 0,4,3 0 2 5 4
The Polygon Triangulation Problem ● Intuitive approach: ear-clipping ● Fast approach: monotone decomposition ● Both involve chopping triangles off in a sequence 1 Polygon Indices 6 6,1,4,2,5 Number of Polygons: 3 3 0,4,3 4,1,3 0 2 5 4
The Polygon Triangulation Problem ● Intuitive approach: ear-clipping ● Fast approach: monotone decomposition ● Both involve chopping triangles off in a sequence 1 Polygon Indices 6 6,1,2,5 Number of Polygons: 3 4 0,4,3 4,1,3 4,2,1 0 2 5 4
The Polygon Triangulation Problem ● Intuitive approach: ear-clipping ● Fast approach: monotone decomposition ● Both involve chopping triangles off in a sequence 1 Polygon Indices 6 6,2,5 Number of Polygons: 3 5 0,4,3 4,1,3 4,2,1 0 2 5 2,6,1 4
The Polygon Triangulation Problem ● Intuitive approach: ear-clipping ● Fast approach: monotone decomposition ● Both involve chopping triangles off in a sequence 1 Polygon Indices 6 6,2,5 Number of Polygons: 3 5 0,4,3 4,1,3 4,2,1 0 2 5 2,6,1 4
The Polygon Triangulation Problem ● Was maintaining the index list convenient? ● NO! ● Original polygon: 6,1,3,0,4,2,5 ● Final polygon: 2,5,6 ● All the removed points were in the middle of the list! ● Maintaining the list can be error prone, and slow for complex models ● Inelegant
Getting Ready Computational geometry requires appropriate data structures! (Lets take a look at one) Triangulation Demo Part 1
Geometric Model Representation ● Geometry describes the shape of model elements (triangles) ● Topology describes how the elements are connected
Manifold Topology ● Each edge joins exactly two faces ● Model is watertight ● Open edges that join to one face are allowed ● Modeling operation consistency Non-manifold Topology rules ● “Invariants”
Topological Data Structures ● Enable elegant and fast traversals ● “Which edges surround a polygon?” ● “Which polygons surround this vertex?” ● Easy to modify geometry ● Split an edge or face to add a new vertex ● Collapse an edge to simplify a mesh
Other Topological Data Structures ● Manifold ● Winged Edge (Baumgart, 1972) ● Half Edge (presented here) ● Quad edge ● Non-manifold ● Radial edge ● Generalized non-manifold
Half Edge Data Structure (HDS) ● Basic topological element is a half edge (HE) ● Geometry is implied by connections* Half Edge Properties HE
Half Edge Data Structure (HDS) ● HE connects a Start point to an End point ● Traversal is StartPt to EndPt (edge is oriented) ● Geometry is a straight Half Edge Properties EndPt EndPt HE StartPt
Half Edge Data Structure (HDS) ● HE points to next half edge in traversal direction ● Start point of HE.next is HE.EndPt Half Edge Properties EndPt Next HE
Half Edge Data Structure (HEDS) ● Traversal directions are consistent Half Edge Properties EndPt Next HE
Half Edge Data Structure (HEDS) ● Note that sequence of half edges forms a loop! ● So far, we only connect points (no polygons yet!) ● Geometry is a wire Half Edge Properties EndPt Next HE
Half Edge Data Structure (HEDS) ● HE may point to a face on its left side ● All half edges in a loop point to same face Half Edge Properties EndPt Face Next Face HE
Half Edge Data Structure (HEDS) ● HE points to its opposite half edge ● Which is attributed as above Half Edge Properties EndPt Next Face Opposite
Half Edge Data Structure (HEDS) ● It is useful to store user data and a marker Half Edge Properties EndPt Next Face Opposite UserData Marker
Simple C++ HDS class definition struct HalfEdgeFace struct HalfEdge { { HalfEdge *halfEdge; HalfEdgeVert *endPt; unsigned char marker; HalfEdge *next; }; HalfEdge *opposite; struct HalfEdgeVert HalfEdgeFace *face; { void *userData; HalfEdge *halfEdge; unsigned char marker; int index; }; unsigned char marker; };
HDS Invariants ● Strict ● halfEdge != halfEdge->opposite ● halfEdge != halfEdge->next ● halfEdge == halfEdge->opposite->opposite ● startPt(halfEdge) == halfEdge->opposite->endPt ● There are a few others… ● Convenience ● Vertex == Vertex->halfEdge->endPt
Simple Traversals Find vertex loop defined by a half edge IndexList FindVertexLoop(HalfEdge *edge) { IndexList loop; Triangulation Demo HalfEdge *curEdge = edge; Part 2 do { loop.push_back(edge.endPt->index); curEdge = curEdge->next; } while (curEdge != edge); return loop; };
Simple Traversals Find vertex loop defined by a half edge IndexList FindVertexLoop(HalfEdge *edge) { IndexList loop; HalfEdge *curEdge = edge; do { loop.push_back(edge.endPt->index); curEdge = curEdge->next; } while (curEdge != edge); return loop; };
Simple Traversals Find vertex loop defined by a half edge IndexList FindVertexLoop(HalfEdge *edge) { IndexList loop; HalfEdge *curEdge = edge; do { loop.push_back(edge.endPt->index); curEdge = curEdge->next; } while (curEdge != edge); return loop; };
Simple Traversals Find vertex loop defined by a half edge IndexList FindVertexLoop(HalfEdge *edge) { IndexList loop; HalfEdge *curEdge = edge; do { loop.push_back(edge.endPt->index); curEdge = curEdge->next; } while (curEdge != edge); return loop; };
Simple Traversals Find vertex loop defined by a half edge IndexList FindVertexLoop(HalfEdge *edge) { IndexList loop; HalfEdge *curEdge = edge; do { loop.push_back(edge.endPt->index); curEdge = curEdge->next; } while (curEdge != edge); return loop; };
Simple Traversals Find vertex loop defined by a half edge IndexList FindVertexLoop(HalfEdge *edge) { IndexList loop; HalfEdge *curEdge = edge; do { loop.push_back(edge.endPt->index); curEdge = curEdge->next; } while (curEdge != edge); return loop; };
Simple Traversals Find vertex loop defined by a half edge IndexList FindVertexLoop(HalfEdge *edge) { IndexList loop; HalfEdge *curEdge = edge; do { loop.push_back(edge.endPt->index); curEdge = curEdge->next; } while (curEdge != edge); return loop; };
Recommend
More recommend