// Copyright (C) 2007 Id Software, Inc. // #ifndef __TRACEMODEL_H__ #define __TRACEMODEL_H__ /* =============================================================================== A trace model is an arbitrary polygonal model which is used by the collision detection system to find collisions, contacts or the contents of a volume. For collision detection speed reasons the number of vertices and edges are limited. The trace model can have any shape. However convex models are usually preferred. =============================================================================== */ class idVec3; class idMat3; class idBounds; class idMaterial; typedef const idMaterial* ( trmMaterialForName_t )( const char* name ); typedef const char* ( trmNameForMaterial_t )( const idMaterial* material ); // trace model type enum traceModel_t { TRM_INVALID, // invalid trm TRM_BOX, // box TRM_OCTAHEDRON, // octahedron TRM_DODECAHEDRON, // dodecahedron TRM_CYLINDER, // cylinder approximation TRM_CONE, // cone approximation TRM_BONE, // two tetrahedrons attached to each other TRM_POLYGON, // arbitrary convex polygon TRM_POLYGONVOLUME, // volume for arbitrary convex polygon TRM_CUSTOM // loaded from map model or ASE/LWO }; // these are bit cache limits #define MAX_TRACEMODEL_VERTS 32 #define MAX_TRACEMODEL_EDGES 32 #define MAX_TRACEMODEL_POLYS 16 #define MAX_TRACEMODEL_POLYEDGES 16 typedef idVec3 traceModelVert_t; struct traceModelEdge_t { int v[2]; idVec3 normal; }; struct traceModelPoly_t { idVec3 normal; float dist; idBounds bounds; int numEdges; int edges[MAX_TRACEMODEL_POLYEDGES]; }; class idTraceModel { public: traceModel_t type; int numVerts; traceModelVert_t verts[MAX_TRACEMODEL_VERTS]; int numEdges; traceModelEdge_t edges[MAX_TRACEMODEL_EDGES+1]; // edges[0] is unused because edge index signs are used for direction int numPolys; traceModelPoly_t polys[MAX_TRACEMODEL_POLYS]; const idMaterial* polyMaterials[MAX_TRACEMODEL_POLYS]; idVec3 offset; // offset to center of model idBounds bounds; // bounds of model bool isConvex; // true when model is convex public: idTraceModel( void ); // axial bounding box idTraceModel( const idBounds &boxBounds ); // cylinder approximation idTraceModel( const idBounds &cylBounds, const int numSides ); // bone idTraceModel( const float length, const float width ); // axial box void SetupBox( const idBounds &boxBounds ); void SetupBox( const float size ); // octahedron void SetupOctahedron( const idBounds &octBounds ); void SetupOctahedron( const float size ); // dodecahedron void SetupDodecahedron( const idBounds &dodBounds ); void SetupDodecahedron( const float size ); // cylinder approximation void SetupCylinder( const idBounds &cylBounds, const int numSides, float offset = 0, int axis = 0 ); void SetupCylinder( const float height, const float width, const int numSides ); // cone approximation void SetupCone( const idBounds &coneBounds, const int numSides ); void SetupCone( const float height, const float width, const int numSides ); // two tetrahedrons attached to each other void SetupBone( const float length, const float width ); // arbitrary convex polygon void SetupPolygon( const idVec3 *v, const int count ); void SetupPolygon( const idWinding &w ); // extruded polygonal prism void SetupPolygonPrism( const idWinding &w, float thickness ); // basically a box, but with the top verts pushed out void SetupFrustum( const idBounds& boxBounds, float topOffset ); void SetNullPolygonMaterials( void ); // generate edge normals int GenerateEdgeNormals( void ); // test whether or not the model is convex and set isConvex accordingly void TestConvexity( void ); // translate the trm void Translate( const idVec3 &translation ); // rotate the trm void Rotate( const idMat3 &rotation ); // shrink the model m units on all sides void Shrink( const float m ); // clear unused spots in the arrays void ClearUnused( void ); // make sure the trace model is well formed bool Verify( void ); // compare bool Compare( const idTraceModel &trm ) const; bool operator==( const idTraceModel &trm ) const; bool operator!=( const idTraceModel &trm ) const; bool ContainsPoint( const idVec3& point ) const; // returns true of the model is a closed surface bool IsClosedSurface( void ) const; // get the area of one of the polygons float GetPolygonArea( int polyNum ) const; // get the silhouette edges int GetProjectionSilhouetteEdges( const idVec3 &projectionOrigin, int silEdges[MAX_TRACEMODEL_EDGES] ) const; int GetParallelProjectionSilhouetteEdges( const idVec3 &projectionDir, int silEdges[MAX_TRACEMODEL_EDGES] ) const; // calculate mass properties assuming an uniform density void GetMassProperties( const float density, float &mass, idVec3 ¢erOfMass, idMat3 &inertiaTensor ) const; void Write( idFile* fp, trmNameForMaterial_t lookup ) const; void Read( idFile* fp, trmMaterialForName_t lookup ); private: void InitBox( void ); void InitOctahedron( void ); void InitDodecahedron( void ); void InitBone( void ); void ProjectionIntegrals( int polyNum, int a, int b, struct projectionIntegrals_t &integrals ) const; void PolygonIntegrals( int polyNum, int a, int b, int c, struct polygonIntegrals_t &integrals ) const; void VolumeIntegrals( struct volumeIntegrals_t &integrals ) const; void VolumeFromPolygon( idTraceModel &trm, float thickness ) const; int GetOrderedSilhouetteEdges( const int edgeIsSilEdge[MAX_TRACEMODEL_EDGES+1], int silEdges[MAX_TRACEMODEL_EDGES] ) const; }; ID_INLINE idTraceModel::idTraceModel( void ) { type = TRM_INVALID; numVerts = numEdges = numPolys = 0; bounds.Zero(); } ID_INLINE idTraceModel::idTraceModel( const idBounds &boxBounds ) { InitBox(); SetupBox( boxBounds ); } ID_INLINE idTraceModel::idTraceModel( const idBounds &cylBounds, const int numSides ) { SetupCylinder( cylBounds, numSides ); } ID_INLINE idTraceModel::idTraceModel( const float length, const float width ) { InitBone(); SetupBone( length, width ); } ID_INLINE bool idTraceModel::operator==( const idTraceModel &trm ) const { return Compare( trm ); } ID_INLINE bool idTraceModel::operator!=( const idTraceModel &trm ) const { return !Compare( trm ); } #endif /* !__TRACEMODEL_H__ */