Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1675 lines
53 KiB

  1. //========= Copyright � Valve Corporation, All rights reserved. ============//
  2. #ifndef SERIALIZE_HDR
  3. #define SERIALIZE_HDR
  4. #include "resourcefile/resourcestream.h"
  5. #include "mathlib/aabb.h"
  6. #include "bitvec.h"
  7. #include "rubikon/serializehelpers.h"
  8. #include "rubikon/constants.h"
  9. #include "tier1/checksum_crc.h"
  10. #include "mathlib/transform.h"
  11. //---------------------------------------------------------------------------------------
  12. // Sphere serialization
  13. //---------------------------------------------------------------------------------------
  14. schema struct RnSphere_t
  15. {
  16. TYPEMETA( MNoScatter )
  17. DECLARE_SCHEMA_DATA_CLASS( RnSphere_t );
  18. AABB_t GetBbox() const;
  19. AABB_t GetBbox( const CTransform& xform ) const;
  20. int GetTriangulation( Vector *pVerts = NULL ) const;
  21. void GetTriangulation( CUtlVector<Vector> &vertices, CUtlVector<uint32> &indices ) const;
  22. void GetTriangulation( CUtlVector<Vector> &vertices, CUtlVector<uint32> &indices, int nSides, int nSlices ) const;
  23. float GetVolume() const;
  24. Vector ComputeOrthographicAreas() const;
  25. Vector m_vCenter;
  26. float32 m_flRadius;
  27. };
  28. inline RnSphere_t operator*( const RnSphere_t& sphere, float flScale )
  29. {
  30. RnSphere_t out;
  31. out.m_vCenter = sphere.m_vCenter * flScale;
  32. out.m_flRadius = sphere.m_flRadius * flScale;
  33. return out;
  34. }
  35. inline RnSphere_t operator*( float flScale, const RnSphere_t& sphere )
  36. {
  37. RnSphere_t out;
  38. out.m_vCenter = sphere.m_vCenter * flScale;
  39. out.m_flRadius = sphere.m_flRadius * flScale;
  40. return out;
  41. }
  42. //---------------------------------------------------------------------------------------
  43. // Capsule serialization
  44. //---------------------------------------------------------------------------------------
  45. schema struct RnCapsule_t
  46. {
  47. TYPEMETA( MNoScatter )
  48. DECLARE_SCHEMA_DATA_CLASS( RnCapsule_t );
  49. AABB_t GetBbox() const;
  50. AABB_t GetBbox( const CTransform& xform ) const;
  51. int GetTriangulation( Vector *pVerts = NULL ) const;
  52. void GetTriangulation( CUtlVector<Vector> &vertices, CUtlVector<uint32> &indices ) const;
  53. void GetTriangulation( CUtlVector<Vector> &vertices, CUtlVector<uint32> &indices, int nSides, int nSlices ) const;
  54. float GetVolume() const;
  55. Vector ComputeOrthographicAreas() const;
  56. Vector m_vCenter[ 2 ];
  57. float32 m_flRadius;
  58. };
  59. inline RnCapsule_t operator*( const RnCapsule_t& capsule, float flScale )
  60. {
  61. RnCapsule_t out;
  62. out.m_vCenter[ 0 ] = capsule.m_vCenter[ 0 ] * flScale;
  63. out.m_vCenter[ 1 ] = capsule.m_vCenter[ 1 ] * flScale;
  64. out.m_flRadius = capsule.m_flRadius * flScale;
  65. return out;
  66. }
  67. inline RnCapsule_t operator*( float flScale, const RnCapsule_t& capsule )
  68. {
  69. RnCapsule_t out;
  70. out.m_vCenter[ 0 ] = capsule.m_vCenter[ 0 ] * flScale;
  71. out.m_vCenter[ 1 ] = capsule.m_vCenter[ 1 ] * flScale;
  72. out.m_flRadius = capsule.m_flRadius * flScale;
  73. return out;
  74. }
  75. //--------------------------------------------------------------------------------------------------
  76. // Ray
  77. //--------------------------------------------------------------------------------------------------
  78. struct RnRay_t
  79. {
  80. RnRay_t( void ) { }
  81. RnRay_t( const Vector& vStart, const Vector& vEnd )
  82. {
  83. vOrigin = vStart;
  84. vDelta = vEnd - vStart;
  85. // Pre-compute inverse
  86. vDeltaInv.x = vDelta.x != 0.0f ? 1.0f / vDelta.x : FLT_MAX;
  87. vDeltaInv.y = vDelta.y != 0.0f ? 1.0f / vDelta.y : FLT_MAX;
  88. vDeltaInv.z = vDelta.z != 0.0f ? 1.0f / vDelta.z : FLT_MAX;
  89. }
  90. VectorAligned vOrigin;
  91. VectorAligned vDelta;
  92. VectorAligned vDeltaInv;
  93. };
  94. //---------------------------------------------------------------------------------------
  95. // Hull serialization
  96. //---------------------------------------------------------------------------------------
  97. schema struct RnPlane_t
  98. {
  99. TYPEMETA( MNoScatter )
  100. DECLARE_SCHEMA_DATA_CLASS( RnPlane_t );
  101. Vector m_vNormal; // The plane normal
  102. float32 m_flOffset; // The plane offset such that P: n*x - d = 0
  103. // Construction
  104. FORCEINLINE RnPlane_t( void ) { }
  105. FORCEINLINE RnPlane_t( const Vector& n, float d ) { m_vNormal = n; m_flOffset = d; }
  106. FORCEINLINE RnPlane_t( const Vector& n, const Vector& p ) { m_vNormal = n; m_flOffset = DotProduct( n, p ); }
  107. // Utilities
  108. FORCEINLINE float Distance( const Vector &vPoint ) const { return DotProduct( m_vNormal, vPoint ) - m_flOffset; }
  109. FORCEINLINE bool IsValid( void ) const { return m_vNormal != vec3_origin; }
  110. FORCEINLINE bool operator == ( const RnPlane_t &other )const { return m_vNormal == other.m_vNormal && m_flOffset == other.m_flOffset; }
  111. };
  112. schema struct RnHalfEdge_t
  113. {
  114. TYPEMETA( MNoScatter )
  115. DECLARE_SCHEMA_DATA_CLASS( RnHalfEdge_t );
  116. uint8 m_nNext; // Next edge index in CCW circular list around face
  117. uint8 m_nTwin; // Twin edge
  118. uint8 m_nOrigin; // Origin vertex index of edge
  119. uint8 m_nFace; // Face index
  120. };
  121. schema struct RnFace_t
  122. {
  123. TYPEMETA( MNoScatter )
  124. DECLARE_SCHEMA_DATA_CLASS( RnFace_t );
  125. uint8 m_nEdge; // Start edge index for CCW circular list around face
  126. };
  127. schema struct RnHull_t
  128. {
  129. TYPEMETA( MNoScatter )
  130. DECLARE_SCHEMA_DATA_CLASS( RnHull_t );
  131. Vector m_vCentroid; // Hull centroid
  132. float m_flMaxAngularRadius; // Angular radius for CCD
  133. CResourceArray< Vector > m_Vertices; // Hull vertices (x1, y1, z1, x2, y2, z2, ...)
  134. CResourceArray< RnPlane_t > m_Planes; // Hull face planes with outward pointing normals (n1, -d1, n2, -d2, ...)
  135. CResourceArray< RnHalfEdge_t > m_Edges; // Hull half edges order such that each edge e is followed by its twin e' (e1, e1', e2, e2', ...)
  136. CResourceArray< RnFace_t > m_Faces; // Hull faces
  137. Vector m_vOrthographicAreas; // fraction 0..1 of coverage along YZ,ZX,XY sides of AABB
  138. matrix3x4_t m_MassProperties; // inertia tensor (in 3x3 part, always PSD) and center of mass (translation)
  139. float m_flVolume;
  140. float m_flMaxMotionRadius;
  141. float m_flMinMotionThickness;
  142. AABB_t m_Bounds;
  143. FORCEINLINE int GetVertexCount( void ) const { return m_Vertices.Count(); }
  144. FORCEINLINE const Vector GetVertex( int nVertex ) const { return m_Vertices[ nVertex ]; }
  145. FORCEINLINE int GetPlaneCount( void ) const { return m_Planes.Count(); }
  146. FORCEINLINE const RnPlane_t& GetPlane( int nFace ) const { return m_Planes[ nFace ]; }
  147. FORCEINLINE const Vector& GetPlaneNormal( int nFace ) const { return m_Planes[ nFace ].m_vNormal; }
  148. FORCEINLINE int GetEdgeCount( void ) const { return m_Edges.Count(); }
  149. FORCEINLINE const RnHalfEdge_t* GetEdge( int nEdge ) const { return &m_Edges[ nEdge ]; }
  150. FORCEINLINE int GetFaceCount( void ) const { return m_Faces.Count(); }
  151. FORCEINLINE const RnFace_t* GetFace( int nFace ) const { return &m_Faces[ nFace ]; }
  152. FORCEINLINE const Vector ComputeFaceCentroid( int nFace )const;
  153. int GetMemory( void ) const;
  154. void Transform( const matrix3x4_t& transform );
  155. AABB_t GetBbox( void ) const;
  156. AABB_t GetBbox( const CTransform& xform ) const;
  157. int GetTriangulation( Vector *pVerts = NULL ) const;
  158. void GetTriangulation( CUtlVector<Vector> &vertices, CUtlVector<uint32> &indices, float flScale = 1.0f ) const;
  159. float GetVolume( void ) const;
  160. FORCEINLINE const Vector &GetCentroid( )const { return m_vCentroid; }
  161. uintp GetRuntimeSize( void ) const;
  162. void Validate( void ) const;
  163. };
  164. inline void ShallowCopy( RnHull_t &dest, const RnHull_t &source )
  165. {
  166. V_memcpy( &dest, &source, sizeof( RnHull_t ) );
  167. dest.m_Vertices = source.m_Vertices;
  168. dest.m_Planes = source.m_Planes;
  169. dest.m_Edges = source.m_Edges;
  170. dest.m_Faces = source.m_Faces;
  171. }
  172. //--------------------------------------------------------------------------------------------------
  173. // Helpers (for stack allocation)
  174. //--------------------------------------------------------------------------------------------------
  175. inline RnHalfEdge_t MakeEdge( uint8 nNext, uint8 nTwin, uint8 nOrigin, uint8 nFace )
  176. {
  177. RnHalfEdge_t e;
  178. e.m_nNext = nNext;
  179. e.m_nTwin = nTwin;
  180. e.m_nOrigin = nOrigin;
  181. e.m_nFace = nFace;
  182. return e;
  183. }
  184. struct RnHullTriangle_t : public RnHull_t
  185. {
  186. void Init( const Vector& v1, const Vector& v2, const Vector& v3 )
  187. {
  188. // Centroid
  189. m_vCentroid = ( v1 + v2 + v3 ) / 3.0f;
  190. // Vertices
  191. Vector TriangleVertices;
  192. m_TriangleVertices[ 0 ] = v1;
  193. m_TriangleVertices[ 1 ] = v2;
  194. m_TriangleVertices[ 2 ] = v3;
  195. m_Vertices.WriteDirect( 3, m_TriangleVertices );
  196. // Planes
  197. Vector n = CrossProduct( v2 - v1, v3 - v1 );
  198. VectorNormalize( n );
  199. m_TrianglePlanes[ 0 ] = RnPlane_t( n, v1 );
  200. m_TrianglePlanes[ 1 ] = RnPlane_t( -n, v1 );
  201. m_Planes.WriteDirect( 2, m_TrianglePlanes );
  202. // Edges (remember that each edge *must* be followed by its twin!)
  203. m_TriangleEdges[ 0 ] = MakeEdge( 2, 1, 0, 0 ); // Face 0 - Edge 0
  204. m_TriangleEdges[ 1 ] = MakeEdge( 5, 0, 1, 1 ); // Face 1 - Edge 0
  205. m_TriangleEdges[ 2 ] = MakeEdge( 4, 3, 1, 0 ); // Face 0 - Edge 1
  206. m_TriangleEdges[ 3 ] = MakeEdge( 1, 2, 2, 1 ); // Face 1 - Edge 1
  207. m_TriangleEdges[ 4 ] = MakeEdge( 0, 5, 2, 0 ); // Face 0 - Edge 2
  208. m_TriangleEdges[ 5 ] = MakeEdge( 3, 4, 0, 1 ); // Face 1 - Edge 2
  209. m_Edges.WriteDirect( 6, m_TriangleEdges );
  210. // Faces
  211. m_TriangleFaces[ 0 ].m_nEdge = 0;
  212. m_TriangleFaces[ 1 ].m_nEdge = 1;
  213. m_Faces.WriteDirect( 2, m_TriangleFaces );
  214. // Bounds
  215. m_Bounds.m_vMinBounds = VectorMin( v1, VectorMin( v2, v3 ) );
  216. m_Bounds.m_vMaxBounds = VectorMax( v1, VectorMax( v2, v3 ) );
  217. }
  218. Vector m_TriangleVertices[ 3 ];
  219. RnPlane_t m_TrianglePlanes[ 2 ];
  220. RnHalfEdge_t m_TriangleEdges[ 6 ];
  221. RnFace_t m_TriangleFaces[ 2 ];
  222. };
  223. struct RnHullBox_t : public RnHull_t
  224. {
  225. void Init( const Vector& vMin, const Vector& vMax )
  226. {
  227. // Centroid
  228. m_vCentroid = 0.5f * ( vMin + vMax );
  229. // Vertices
  230. Vector vExtent = vMax - m_vCentroid;
  231. float ex = vExtent.x;
  232. float ey = vExtent.y;
  233. float ez = vExtent.z;
  234. m_BoxVertices[ 0 ] = m_vCentroid + Vector( ex, ey, ez );
  235. m_BoxVertices[ 1 ] = m_vCentroid + Vector( -ex, ey, ez );
  236. m_BoxVertices[ 2 ] = m_vCentroid + Vector( -ex, -ey, ez );
  237. m_BoxVertices[ 3 ] = m_vCentroid + Vector( ex, -ey, ez );
  238. m_BoxVertices[ 4 ] = m_vCentroid + Vector( ex, ey, -ez );
  239. m_BoxVertices[ 5 ] = m_vCentroid + Vector( -ex, ey, -ez );
  240. m_BoxVertices[ 6 ] = m_vCentroid + Vector( -ex, -ey, -ez );
  241. m_BoxVertices[ 7 ] = m_vCentroid + Vector( ex, -ey, -ez );
  242. m_Vertices.WriteDirect( 8, m_BoxVertices );
  243. // Planes
  244. Vector vAxisX( 1, 0, 0 );
  245. Vector vAxisY( 0, 1, 0 );
  246. Vector vAxisZ( 0, 0, 1 );
  247. m_BoxPlanes[ 0 ] = RnPlane_t( -vAxisX, vMin );
  248. m_BoxPlanes[ 1 ] = RnPlane_t( vAxisX, vMax );
  249. m_BoxPlanes[ 2 ] = RnPlane_t( -vAxisY, vMin );
  250. m_BoxPlanes[ 3 ] = RnPlane_t( vAxisY, vMax );
  251. m_BoxPlanes[ 4 ] = RnPlane_t( -vAxisZ, vMin );
  252. m_BoxPlanes[ 5 ] = RnPlane_t( vAxisZ, vMax );
  253. m_Planes.WriteDirect( 6, m_BoxPlanes );
  254. // Edges (remember that each edge *must* be followed by its twin!)
  255. m_BoxEdges[ 0 ] = MakeEdge( 2, 1, 2, 0 );
  256. m_BoxEdges[ 1 ] = MakeEdge( 17, 0, 1, 5 );
  257. m_BoxEdges[ 2 ] = MakeEdge( 4, 3, 1, 0 );
  258. m_BoxEdges[ 3 ] = MakeEdge( 20, 2, 5, 3 );
  259. m_BoxEdges[ 4 ] = MakeEdge( 6, 5, 5, 0 );
  260. m_BoxEdges[ 5 ] = MakeEdge( 23, 4, 6, 4 );
  261. m_BoxEdges[ 6 ] = MakeEdge( 0, 7, 6, 0 );
  262. m_BoxEdges[ 7 ] = MakeEdge( 18, 6, 2, 2 );
  263. m_BoxEdges[ 8 ] = MakeEdge( 10, 9, 0, 1 );
  264. m_BoxEdges[ 9 ] = MakeEdge( 21, 8, 3, 5 );
  265. m_BoxEdges[ 10 ] = MakeEdge( 12, 11, 3, 1 );
  266. m_BoxEdges[ 11 ] = MakeEdge( 16, 10, 7, 2 );
  267. m_BoxEdges[ 12 ] = MakeEdge( 14, 13, 7, 1 );
  268. m_BoxEdges[ 13 ] = MakeEdge( 19, 12, 4, 4 );
  269. m_BoxEdges[ 14 ] = MakeEdge( 8, 15, 4, 1 );
  270. m_BoxEdges[ 15 ] = MakeEdge( 22, 14, 0, 3 );
  271. m_BoxEdges[ 16 ] = MakeEdge( 7, 17, 3, 2 );
  272. m_BoxEdges[ 17 ] = MakeEdge( 9, 16, 2, 5 );
  273. m_BoxEdges[ 18 ] = MakeEdge( 11, 19, 6, 2 );
  274. m_BoxEdges[ 19 ] = MakeEdge( 5, 18, 7, 4 );
  275. m_BoxEdges[ 20 ] = MakeEdge( 15, 21, 1, 3 );
  276. m_BoxEdges[ 21 ] = MakeEdge( 1, 20, 0, 5 );
  277. m_BoxEdges[ 22 ] = MakeEdge( 3, 23, 4, 3 );
  278. m_BoxEdges[ 23 ] = MakeEdge( 13, 22, 5, 4 );
  279. m_Edges.WriteDirect( 24, m_BoxEdges );
  280. // Faces
  281. m_BoxFaces[ 0 ].m_nEdge = 0;
  282. m_BoxFaces[ 1 ].m_nEdge = 8;
  283. m_BoxFaces[ 2 ].m_nEdge = 16;
  284. m_BoxFaces[ 3 ].m_nEdge = 20;
  285. m_BoxFaces[ 4 ].m_nEdge = 19;
  286. m_BoxFaces[ 5 ].m_nEdge = 21;
  287. m_Faces.WriteDirect( 6, m_BoxFaces );
  288. // Bounds
  289. m_Bounds.m_vMinBounds = vMin;
  290. m_Bounds.m_vMaxBounds = vMax;
  291. }
  292. Vector m_BoxVertices[ 8 ];
  293. RnPlane_t m_BoxPlanes[ 6 ];
  294. RnHalfEdge_t m_BoxEdges[ 24 ];
  295. RnFace_t m_BoxFaces[ 6 ];
  296. };
  297. //--------------------------------------------------------------------------------------------------
  298. // Mesh serialization
  299. //--------------------------------------------------------------------------------------------------
  300. #define RN_TYPE_SPLIT_X 0
  301. #define RN_TYPE_SPLIT_Y 1
  302. #define RN_TYPE_SPLIT_Z 2
  303. #define RN_TYPE_LEAF 3
  304. schema struct RnTriangle_t
  305. {
  306. TYPEMETA( MNoScatter )
  307. DECLARE_SCHEMA_DATA_CLASS( RnTriangle_t );
  308. int32 m_nIndex[ 3 ];
  309. };
  310. // TODO: this wants to be ALIGN32, but it's currently stored in CUtlVector and CResourceArray, which do not support this.
  311. schema struct ALIGN16 RnNode_t // node needs to not stride over cache line boundary and min/max vectors need to be aligned for easy SIMD loading
  312. {
  313. TYPEMETA( MNoScatter )
  314. DECLARE_SCHEMA_DATA_CLASS( RnNode_t );
  315. Vector m_vMin; // The node AABB
  316. uint32 m_nChildren; // The 2nd child offset and the node type/split axis
  317. Vector m_vMax; // The node AABB
  318. uint32 m_nTriangleOffset; // If leaf node this is the offset into the associated triangle array
  319. // Traversal
  320. FORCEINLINE bool IsLeaf( void ) const { return GetType() == RN_TYPE_LEAF; }
  321. FORCEINLINE RnNode_t* GetLeftChild( void ) { return this + 1; }
  322. FORCEINLINE const RnNode_t* GetLeftChild( void ) const { return this + 1; }
  323. FORCEINLINE RnNode_t* GetRightChild( void ) { return this + GetChildOffset(); }
  324. FORCEINLINE const RnNode_t* GetRightChild( void ) const { return this + GetChildOffset(); }
  325. FORCEINLINE uint GetAxis( void ) const { AssertDbg( !IsLeaf() ); return m_nChildren >> 30; }
  326. FORCEINLINE uint GetChildOffset( void) const { AssertDbg( !IsLeaf() ); return m_nChildren & 0x3FFFFFFF; }
  327. FORCEINLINE uint GetType( void ) const { return m_nChildren >> 30; }
  328. FORCEINLINE uint GetTriangleCount( void ) const { AssertDbg( IsLeaf() ); return m_nChildren & 0x3FFFFFFF; }
  329. FORCEINLINE uint GetTriangleOffset( void ) const { AssertDbg( IsLeaf() ); return m_nTriangleOffset; }
  330. FORCEINLINE void SetTriangleOffset( uint32 nTriangleOffset ) { AssertDbg( IsLeaf( ) ); m_nTriangleOffset = nTriangleOffset; }
  331. // Construction
  332. void SetLeaf( uint nOffset, uint nCount )
  333. {
  334. m_nTriangleOffset = nOffset;
  335. m_nChildren = ( RN_TYPE_LEAF << 30 ) | nCount;
  336. }
  337. void SetNode( uint nAxis, uint nChildOffset )
  338. {
  339. AssertDbg( nAxis < 3 );
  340. m_nChildren = ( nAxis << 30 ) | nChildOffset;
  341. }
  342. // Statistics
  343. int GetHeight( void ) const;
  344. } ALIGN16_POST;
  345. schema struct RnMesh_t
  346. {
  347. TYPEMETA( MNoScatter )
  348. DECLARE_SCHEMA_DATA_CLASS( RnMesh_t );
  349. Vector m_vMin; // The mesh AABB
  350. Vector m_vMax; // The mesh AABB
  351. CResourceArray< RnNode_t > m_Nodes; // The nodes of the loose kd-tree to accelerate ray casts and volume queries against this mesh.
  352. CResourceArray< Vector > m_Vertices; // The mesh vertices in the space of the parent shape.
  353. CResourceArray< RnTriangle_t > m_Triangles; // The mesh triangles with additional topology information similar to the half-edge data structure.
  354. CResourceArray< uint8 > m_Materials; // The per-triangle material indices for this mesh. Can be empty if all triangles share the same material.
  355. Vector m_vOrthographicAreas; // fraction 0..1 of coverage along YZ,ZX,XY sides of AABB
  356. FORCEINLINE RnNode_t* GetRoot( void ) { return &m_Nodes[ 0 ]; }
  357. FORCEINLINE const RnNode_t* GetRoot( void ) const { return &m_Nodes[ 0 ]; }
  358. FORCEINLINE int GetVertexCount( void ) const { return m_Vertices.Count(); }
  359. FORCEINLINE const Vector &GetVertex( int nVertex ) const { return m_Vertices[ nVertex ]; }
  360. FORCEINLINE int GetTriangleCount( void ) const { return m_Triangles.Count(); }
  361. FORCEINLINE const RnTriangle_t* GetTriangle( int nTriangle ) const { return &m_Triangles[ nTriangle ]; }
  362. FORCEINLINE int GetMaterialCount( void ) const { return m_Materials.Count(); }
  363. FORCEINLINE uint8 GetMaterial( int nMaterial ) const { return m_Materials[ nMaterial ]; }
  364. FORCEINLINE const Vector ComputeTriangleUnitNormal( const Vector &vScale, int nIndex )const;
  365. FORCEINLINE const Vector ComputeTriangleCentroid( int nIndex )const;
  366. FORCEINLINE const Vector ComputeTriangleIncenter( int nIndex )const; // the center of inscribed circle
  367. // Statistics
  368. int GetHeight( void ) const;
  369. int GetMemory( void ) const;
  370. AABB_t GetBbox( void ) const;
  371. int GetTriangulation( Vector *pVerts = NULL ) const;
  372. void GetTriangulation( CUtlVector<Vector> &vertices, CUtlVector<uint32> &indices, const Vector &vScale = Vector( 1, 1, 1 ) ) const;
  373. float GetVolume( void ) const { return 0; }
  374. uintp GetRuntimeSize( void ) const ;
  375. void Validate( void ) const;
  376. template < typename Functor >
  377. void CastBox( const Functor &callback, const RnRay_t& localRay, const Vector& vExtent, float flMaxFraction ) const;
  378. };
  379. //--------------------------------------------------------------------------------------------------
  380. // Shape serialization
  381. //--------------------------------------------------------------------------------------------------
  382. schema struct RnShapeDesc_t
  383. {
  384. TYPEMETA( MNoScatter )
  385. DECLARE_SCHEMA_DATA_CLASS( RnShapeDesc_t );
  386. uint32 m_nCollisionAttributeIndex;
  387. uint32 m_nSurfacePropertyIndex;
  388. };
  389. schema struct RnSphereDesc_t : public RnShapeDesc_t
  390. {
  391. TYPEMETA( MNoScatter )
  392. DECLARE_SCHEMA_DATA_CLASS( RnSphereDesc_t );
  393. RnSphere_t m_Sphere;
  394. };
  395. schema struct RnCapsuleDesc_t : public RnShapeDesc_t
  396. {
  397. TYPEMETA( MNoScatter )
  398. DECLARE_SCHEMA_DATA_CLASS( RnCapsuleDesc_t );
  399. RnCapsule_t m_Capsule;
  400. };
  401. schema struct RnHullDesc_t : public RnShapeDesc_t
  402. {
  403. TYPEMETA( MNoScatter )
  404. DECLARE_SCHEMA_DATA_CLASS( RnHullDesc_t );
  405. RnHull_t m_Hull;
  406. };
  407. schema struct RnMeshDesc_t : public RnShapeDesc_t
  408. {
  409. TYPEMETA( MNoScatter )
  410. DECLARE_SCHEMA_DATA_CLASS( RnMeshDesc_t );
  411. RnMesh_t m_Mesh;
  412. };
  413. //--------------------------------------------------------------------------------------------------
  414. template <typename Array>
  415. uintp GetRuntimeSizeOf( const Array & arr )
  416. {
  417. return sizeof( arr[0] ) * uintp( arr.Count() );
  418. }
  419. //--------------------------------------------------------------------------------------------------
  420. inline uintp RnHull_t::GetRuntimeSize( void ) const
  421. {
  422. return sizeof( *this ) +
  423. GetRuntimeSizeOf( m_Vertices ) +
  424. GetRuntimeSizeOf( m_Planes ) +
  425. GetRuntimeSizeOf( m_Edges ) +
  426. GetRuntimeSizeOf( m_Faces );
  427. }
  428. //--------------------------------------------------------------------------------------------------
  429. inline uintp RnMesh_t::GetRuntimeSize( void ) const
  430. {
  431. return ( ( sizeof( *this ) + 15 ) & ~15 ) +
  432. GetRuntimeSizeOf( m_Nodes ) +
  433. GetRuntimeSizeOf( m_Vertices ) +
  434. GetRuntimeSizeOf( m_Triangles ) +
  435. GetRuntimeSizeOf( m_Materials );
  436. }
  437. //--------------------------------------------------------------------------------------------------
  438. inline void RnHull_t::Validate( void ) const
  439. {
  440. #ifdef DBGFLAG_ASSERT
  441. Assert( m_flMaxAngularRadius > 0 && m_flMaxAngularRadius < 1e5f && m_vCentroid.Length() < 1e4f && uint( m_Vertices.Count() ) < 256 && uint( m_Planes.Count() ) < 256 && uint( m_Edges.Count() ) < 256 && uint( m_Faces.Count() ) < 256 );
  442. for( int i = 0; i < m_Faces.Count(); ++i )
  443. {
  444. Assert( m_Faces[i].m_nEdge < ( uint )m_Edges.Count() );
  445. }
  446. for( int i = 0; i < m_Edges.Count(); ++i )
  447. {
  448. Assert( m_Edges[i].m_nNext < ( uint )m_Edges.Count() );
  449. Assert( m_Edges[i].m_nTwin < ( uint )m_Edges.Count() );
  450. Assert( m_Edges[i].m_nOrigin < ( uint )m_Vertices.Count() );
  451. Assert( m_Edges[i].m_nFace < ( uint )m_Faces.Count() );
  452. }
  453. #endif
  454. }
  455. //--------------------------------------------------------------------------------------------------
  456. inline void RnMesh_t::Validate( void ) const
  457. {
  458. #ifdef DBGFLAG_ASSERT
  459. Assert( m_vMin.Length() < 1e5f && m_vMax.Length() < 1e5f ); // check saneness
  460. //for( int i = 0; i < m_Nodes.Count(); ++i )
  461. {
  462. }
  463. for( int i = 0; i < m_Vertices.Count(); ++i )
  464. {
  465. Assert( m_Vertices[i].Length() < 1e5f );
  466. }
  467. #endif
  468. }
  469. //--------------------------------------------------------------------------------------------------
  470. // Joint serialization
  471. //--------------------------------------------------------------------------------------------------
  472. struct RnJointDesc_t
  473. {
  474. // Bodies
  475. uint32 m_nBody1;
  476. uint32 m_nBody2;
  477. // Joint frames
  478. Vector m_vOrigin1;
  479. Quaternion m_qBasis1;
  480. Vector m_vOrigin2;
  481. Quaternion m_qBasis2;
  482. // Breakable
  483. float m_flMaxForce;
  484. float m_flMaxTorque;
  485. };
  486. struct RnSphericalDesc_t : public RnJointDesc_t
  487. {
  488. // Angular motor (3D)
  489. Vector m_vTargetVelocity;
  490. float m_flMaxTorque;
  491. };
  492. struct RnUniversalDesc_t : public RnJointDesc_t
  493. {
  494. // Limit
  495. float m_flConeAngle;
  496. };
  497. struct RnRevoluteDesc_t : public RnJointDesc_t
  498. {
  499. // Limit
  500. float m_flMinAngle;
  501. float m_flMaxAngle;
  502. // Angular motor (1D)
  503. float m_flTargetVelocity;
  504. float m_flMaxTorque;
  505. };
  506. struct RnPrismaticDesc_t : public RnJointDesc_t
  507. {
  508. // Limit
  509. float m_flMinDistance;
  510. float m_flMaxDistance;
  511. // Linear motor (1D)
  512. float m_flTargetVelocity;
  513. float m_flMaxForce;
  514. };
  515. struct RnRagdollDesc_t : public RnJointDesc_t
  516. {
  517. // Conical limit with elliptical base
  518. float32 m_flRadiusY;
  519. float32 m_flRadiusZ;
  520. // Angular motor (3D)
  521. Vector m_vTargetVelocity;
  522. float32 m_flMaxTorque;
  523. };
  524. struct rnWeldDesc_t : public RnJointDesc_t
  525. {
  526. // Spring parameters
  527. float m_flFrequency;
  528. float m_flDampingRatio;
  529. };
  530. struct rnPulleyDesc_t : public RnJointDesc_t
  531. {
  532. };
  533. struct rnSpringDesc_t : public RnJointDesc_t
  534. {
  535. // Spring parameters
  536. float32 m_flFrequency;
  537. float32 m_flDampingRatio;
  538. };
  539. schema struct RnSoftbodyParticle_t
  540. {
  541. TYPEMETA( MNoScatter )
  542. DECLARE_SCHEMA_DATA_CLASS( RnSoftbodyParticle_t );
  543. float32 m_flMassInv;
  544. };
  545. schema struct RnSoftbodySpring_t
  546. {
  547. TYPEMETA( MNoScatter )
  548. DECLARE_SCHEMA_DATA_CLASS( RnSoftbodySpring_t );
  549. uint16 m_nParticle[2];
  550. float32 m_flLength;
  551. };
  552. schema struct RnSoftbodyCapsule_t
  553. {
  554. TYPEMETA( MNoScatter )
  555. DECLARE_SCHEMA_DATA_CLASS( RnSoftbodyCapsule_t );
  556. Vector m_vCenter[2];
  557. float32 m_flRadius;
  558. uint16 m_nParticle[2];
  559. };
  560. schema struct ALIGN16 RnBlendVertex_t
  561. {
  562. TYPEMETA( MNoScatter )
  563. DECLARE_SCHEMA_DATA_CLASS( RnBlendVertex_t );
  564. uint16 m_nWeight0;
  565. uint16 m_nIndex0;
  566. uint16 m_nWeight1;
  567. uint16 m_nIndex1;
  568. uint16 m_nWeight2;
  569. uint16 m_nIndex2;
  570. uint16 m_nFlags;
  571. uint16 m_nTargetIndex;
  572. };
  573. inline Vector RnSphere_t::ComputeOrthographicAreas()const
  574. {
  575. return Vector( M_PI/4, M_PI/4, M_PI/4 );
  576. }
  577. // compute the area of 2D capsule with the given 2 centers and the radius
  578. inline float Compute2DCapsuleArea( float x0, float y0, float x1, float y1, float flRadius )
  579. {
  580. // it's really simple: the 2D pill, if you don't think of it as 2 circles and a rectangle, but think of it as 2 half-circles and a rectangle,
  581. // has no overlapping parts and is easy to compute the area of
  582. float flAxisLength = sqrtf( Sqr( x0 - x1 ) + Sqr( y0 - y1 ) );
  583. return M_PI * flRadius * flRadius + flAxisLength * 2 * flRadius;
  584. }
  585. inline float Compute2DCapsuleOrthographicArea( float x0, float y0, float x1, float y1, float flRadius )
  586. {
  587. float flBboxArea = ( fabsf( x0 - x1 ) + 2 * flRadius ) * ( fabsf( y0 - y1 ) + 2 * flRadius ); // the area of bounding rectangle
  588. return Compute2DCapsuleArea( x0, y0, x1, y1, flRadius ) / flBboxArea;
  589. }
  590. inline Vector RnCapsule_t::ComputeOrthographicAreas()const
  591. {
  592. return Vector(
  593. Compute2DCapsuleOrthographicArea( m_vCenter[0].x, m_vCenter[0].y, m_vCenter[1].x, m_vCenter[1].y, m_flRadius ),
  594. Compute2DCapsuleOrthographicArea( m_vCenter[0].y, m_vCenter[0].z, m_vCenter[1].y, m_vCenter[1].z, m_flRadius ),
  595. Compute2DCapsuleOrthographicArea( m_vCenter[0].z, m_vCenter[0].x, m_vCenter[1].z, m_vCenter[1].x, m_flRadius )
  596. );
  597. }
  598. inline bool IsTriangulationValid( int nVertexCount, const CUtlVector<uint32> &indices )
  599. {
  600. if( nVertexCount == 0 )
  601. {
  602. return indices.IsEmpty(); // triangulation is valid iff both indices and vertices are empty
  603. }
  604. // check that indices are referring to all the vertices, and no more
  605. CVarBitVecT<uint32> used( nVertexCount );
  606. for( int i = 0; i < indices.Count(); ++i )
  607. {
  608. if( indices[i] < ( uint )nVertexCount )
  609. {
  610. used.Set( indices[i] );
  611. }
  612. else
  613. {
  614. return false;
  615. }
  616. }
  617. uint nUnusedVerts = 0;
  618. for( int i = 0; i < nVertexCount; ++i )
  619. {
  620. if( !used[ i ] )
  621. {
  622. nUnusedVerts++;
  623. Warning( "%d,", i );
  624. }
  625. }
  626. if ( nUnusedVerts )
  627. {
  628. Warning( " fully %u verts are unused\n", nUnusedVerts );
  629. }
  630. //bool bIsAllSet = used.IsAllSet();
  631. return true; // even if we don't use some verts, the triangulation is still valid; it's just not optimal
  632. }
  633. inline bool IsTriangulationValid( const CUtlVector<Vector> &vertices, const CUtlVector<uint32> &indices )
  634. {
  635. return IsTriangulationValid( vertices.Count(), indices );
  636. }
  637. //--------------------------------------------------------------------------------------------------
  638. // RnHull_t
  639. //--------------------------------------------------------------------------------------------------
  640. inline void RnHull_t::Transform( const matrix3x4_t& transform )
  641. {
  642. m_vCentroid = VectorTransform( m_vCentroid, transform );
  643. for ( int nVertex = 0; nVertex < m_Vertices.Count(); ++nVertex )
  644. {
  645. m_Vertices[ nVertex ] = VectorTransform( m_Vertices[ nVertex ], transform );
  646. }
  647. Vector vOrigin = transform.GetOrigin();
  648. for ( int nPlane = 0; nPlane < m_Planes.Count(); ++nPlane )
  649. {
  650. Vector vNormal = VectorRotate( m_Planes[ nPlane ].m_vNormal, transform );
  651. float flOffset = m_Planes[ nPlane ].m_flOffset + DotProduct( vNormal, vOrigin );
  652. m_Planes[ nPlane ].m_vNormal = vNormal;
  653. m_Planes[ nPlane ].m_flOffset = flOffset;
  654. }
  655. }
  656. //--------------------------------------------------------------------------------------------------
  657. // RnNode_t
  658. //--------------------------------------------------------------------------------------------------
  659. inline int RnNode_t::GetHeight( void ) const
  660. {
  661. if ( IsLeaf() )
  662. {
  663. return 0;
  664. }
  665. const RnNode_t* pLeftChild = GetLeftChild();
  666. int LeftHeight = pLeftChild->GetHeight();
  667. const RnNode_t* pRightChild = GetRightChild();
  668. int RightHeight = pRightChild->GetHeight();
  669. return 1 + MAX( LeftHeight, RightHeight );
  670. }
  671. //--------------------------------------------------------------------------------------------------
  672. // RnMesh_t
  673. //--------------------------------------------------------------------------------------------------
  674. inline int RnMesh_t::GetHeight( void ) const
  675. {
  676. const RnNode_t* Root = GetRoot();
  677. if ( Root == NULL )
  678. {
  679. return 0;
  680. }
  681. return Root->GetHeight();
  682. }
  683. //--------------------------------------------------------------------------------------------------
  684. inline int RnHull_t::GetMemory( void ) const
  685. {
  686. int nMemory = 0;
  687. nMemory += sizeof( RnHull_t );
  688. nMemory += m_Vertices.Count() * sizeof( m_Vertices[0] );
  689. nMemory += m_Planes.Count() * sizeof( m_Planes[0] );
  690. nMemory += m_Edges.Count() * sizeof( m_Edges[0] );
  691. nMemory += m_Faces.Count() * sizeof( m_Faces[0] );
  692. return nMemory;
  693. }
  694. //--------------------------------------------------------------------------------------------------
  695. inline int RnMesh_t::GetMemory( void ) const
  696. {
  697. int nMemory = 0;
  698. nMemory += sizeof( RnMesh_t );
  699. nMemory += m_Nodes.Count() * sizeof( RnNode_t );
  700. nMemory += m_Vertices.Count() * sizeof( Vector );
  701. nMemory += m_Triangles.Count() * sizeof( RnTriangle_t );
  702. nMemory += m_Materials.Count() * sizeof( uint8 );
  703. return nMemory;
  704. }
  705. //--------------------------------------------------------------------------------------------------
  706. inline AABB_t RnSphere_t::GetBbox()const
  707. {
  708. AABB_t b;
  709. b.m_vMinBounds.Init( m_vCenter.x - m_flRadius, m_vCenter.y - m_flRadius, m_vCenter.z - m_flRadius );
  710. b.m_vMaxBounds.Init( m_vCenter.x + m_flRadius, m_vCenter.y + m_flRadius, m_vCenter.z + m_flRadius );
  711. return b;
  712. }
  713. //--------------------------------------------------------------------------------------------------
  714. inline AABB_t RnSphere_t::GetBbox( const CTransform& xform ) const
  715. {
  716. Vector vCenter = TransformPoint( xform, m_vCenter );
  717. Vector vExtent( m_flRadius, m_flRadius, m_flRadius );
  718. Vector vMin = vCenter - vExtent;
  719. Vector vMax = vCenter + vExtent;
  720. return AABB_t( vMin, vMax );
  721. }
  722. //--------------------------------------------------------------------------------------------------
  723. inline int RnSphere_t::GetTriangulation( Vector *pVerts ) const
  724. {
  725. if( pVerts )
  726. {
  727. float flSin[5] = {0,1,0,-1,0};
  728. float flCos[5] = {1,0,-1,0,1};
  729. Vector *pOut = pVerts;
  730. for( int i = 0; i < 4; ++i )
  731. {
  732. float s0 = flSin[i] * m_flRadius, c0 = flCos[i] * m_flRadius, s1 = flSin[i+1] * m_flRadius, c1 = flCos[i+1] * m_flRadius;
  733. *pOut++ = m_vCenter + Vector( -m_flRadius, 0, 0 );
  734. *pOut++ = m_vCenter + Vector( 0, c0, s0 );
  735. *pOut++ = m_vCenter + Vector( 0, c1, s1 );
  736. *pOut++ = m_vCenter + Vector( m_flRadius, 0, 0 );
  737. *pOut++ = m_vCenter + Vector( 0, c1, s1 );
  738. *pOut++ = m_vCenter + Vector( 0, c0, s0 );
  739. }
  740. Assert( 24 == pOut - pVerts );
  741. }
  742. return 24; // approximation with octahedron
  743. }
  744. //--------------------------------------------------------------------------------------------------
  745. inline void RnSphere_t::GetTriangulation( CUtlVector<Vector> &vertices, CUtlVector<uint32> &indices )const
  746. {
  747. GetTriangulation( vertices, indices, 12, 5 );
  748. }
  749. //--------------------------------------------------------------------------------------------------
  750. inline void RnSphere_t::GetTriangulation( CUtlVector<Vector> &vertices, CUtlVector<uint32> &indices, int nSides, int nSlices )const
  751. {
  752. int nIndexBase = indices.AddMultipleToTail( nSides * 2 * nSlices * 3 );
  753. uint32 *pOut = indices.Base() + nIndexBase;
  754. int nVertBase = vertices.AddMultipleToTail( nSides * nSlices + 2 );
  755. Vector *pVerts = vertices.Base() + nVertBase;
  756. V_memset( pVerts, 0, ( nSides * nSlices + 2 ) * sizeof( Vector ) );
  757. pVerts[ nSides * nSlices + 0 ] = Vector( -m_flRadius, 0, 0 );
  758. pVerts[ nSides * nSlices + 1 ] = Vector( m_flRadius, 0, 0 );
  759. for( int i = 0; i < nSides; ++i )
  760. {
  761. float theta = ( -2 * M_PI * i ) / nSides;
  762. float s0 = m_flRadius * sinf( theta ), c0 = m_flRadius * cosf( theta );
  763. int i1 = ( i + 1 ) % nSides;
  764. // sides
  765. for( int j = 0; ; ++j )
  766. {
  767. float psi = ( j + 1 ) * M_PI / ( nSlices + 1 ) - M_PI / 2, x0 = sinf( psi ), y0 = cosf( psi );
  768. pVerts[ nSlices * i + j ] = Vector( x0 * m_flRadius, c0 * y0, s0 * y0 );
  769. if( j + 1 < nSlices )
  770. {
  771. *pOut++ = nVertBase + nSlices * i1 + j ;
  772. *pOut++ = nVertBase + nSlices * i + j ;
  773. *pOut++ = nVertBase + nSlices * i1 + j + 1;
  774. *pOut++ = nVertBase + nSlices * i1 + j + 1;
  775. *pOut++ = nVertBase + nSlices * i + j ;
  776. *pOut++ = nVertBase + nSlices * i + j + 1;
  777. Assert( nVertBase + nSlices * i + j + 1 < vertices.Count() );
  778. }
  779. else
  780. {
  781. break;
  782. }
  783. }
  784. // the last slice - only triangles
  785. // the end of caps
  786. if( 1 )
  787. {
  788. *pOut++ = nVertBase + nSlices * nSides + 0;
  789. *pOut++ = nVertBase + nSlices * i ;
  790. *pOut++ = nVertBase + nSlices * i1 ;
  791. }
  792. if( 1 )
  793. {
  794. *pOut++ = nVertBase + nSlices * nSides + 1;
  795. *pOut++ = nVertBase + nSlices * i1 + nSlices - 1;
  796. *pOut++ = nVertBase + nSlices * i + nSlices - 1;
  797. }
  798. }
  799. for( int i = 0; i < nSides * nSlices + 2; ++i )
  800. {
  801. pVerts[i] += m_vCenter;
  802. }
  803. //indices.SetCount( pOut - indices.Base() );
  804. Assert( pOut == indices.end() );
  805. AssertDbg( IsTriangulationValid( vertices, indices ) );
  806. }
  807. //--------------------------------------------------------------------------------------------------
  808. inline AABB_t RnCapsule_t::GetBbox() const
  809. {
  810. AABB_t b;
  811. b.m_vMinBounds.Init( Min( m_vCenter[0].x, m_vCenter[1].x ) - m_flRadius, Min( m_vCenter[0].y, m_vCenter[1].y ) - m_flRadius, Min( m_vCenter[0].z, m_vCenter[1].z ) - m_flRadius );
  812. b.m_vMaxBounds.Init( Max( m_vCenter[0].x, m_vCenter[1].x ) + m_flRadius, Max( m_vCenter[0].y, m_vCenter[1].y ) + m_flRadius, Max( m_vCenter[0].z, m_vCenter[1].z ) + m_flRadius );
  813. return b;
  814. }
  815. //--------------------------------------------------------------------------------------------------
  816. inline AABB_t RnCapsule_t::GetBbox( const CTransform& xform ) const
  817. {
  818. Vector vCenter1 = TransformPoint( xform, m_vCenter[ 0 ] );
  819. Vector vCenter2 = TransformPoint( xform, m_vCenter[ 1 ] );
  820. Vector vExtent( m_flRadius, m_flRadius, m_flRadius );
  821. AABB_t aabb1( vCenter1 - vExtent, vCenter1 + vExtent );
  822. AABB_t aabb2( vCenter2 - vExtent, vCenter2 + vExtent );
  823. return aabb1 + aabb2;
  824. }
  825. //--------------------------------------------------------------------------------------------------
  826. inline int RnCapsule_t::GetTriangulation( Vector *pVerts ) const
  827. {
  828. int nSides = 12, nSlices = 2;
  829. if( pVerts )
  830. {
  831. Vector vHeight = m_vCenter[1] - m_vCenter[0];
  832. float flHeight = vHeight.Length();
  833. Vector vAxisX;
  834. if( flHeight > 1e-5f )
  835. {
  836. vAxisX = vHeight / flHeight;
  837. }
  838. else
  839. {
  840. vAxisX = vHeight = Vector( 1,0,0 );
  841. flHeight = 1;
  842. }
  843. Vector vAxisY = VectorPerpendicularToVector( vAxisX ), vAxisZ = CrossProduct( vAxisX, vAxisY );
  844. Vector *pOut = pVerts;
  845. float s0 = 0, c0 = m_flRadius;
  846. for( int i = 0; i < nSides; ++i )
  847. {
  848. float theta = (2 * M_PI * ( i + 1 ) ) / nSides;
  849. float s1 = m_flRadius * sinf( theta ), c1 = m_flRadius * cosf( theta );
  850. // cylinder sides
  851. *pOut++ = Vector( 0, c1, s1 );
  852. *pOut++ = Vector( 0, c0, s0 );
  853. *pOut++ = Vector( flHeight, c1, s1 );
  854. *pOut++ = Vector( flHeight, c1, s1 );
  855. *pOut++ = Vector( 0, c0, s0 );
  856. *pOut++ = Vector( flHeight, c0, s0 );
  857. // caps - quads
  858. float x0 = 0, x1 = 0, y0 = 1, y1 = 0;
  859. for( int j = 0; j < nSlices; ++j )
  860. {
  861. float psi = ( ( j + 1 ) * M_PI / 2 ) / ( nSlices + 1 );
  862. x1 = sinf( psi );
  863. y1 = cosf( psi );
  864. // top cap
  865. *pOut++ = Vector( flHeight + x0 * m_flRadius, c1 * y0, s1 * y0 );
  866. *pOut++ = Vector( flHeight + x0 * m_flRadius, c0 * y0, s0 * y0 );
  867. *pOut++ = Vector( flHeight + x1 * m_flRadius, c1 * y1, s1 * y1 );
  868. *pOut++ = Vector( flHeight + x1 * m_flRadius, c1 * y1, s1 * y1 );
  869. *pOut++ = Vector( flHeight + x0 * m_flRadius, c0 * y0, s0 * y0 );
  870. *pOut++ = Vector( flHeight + x1 * m_flRadius, c0 * y1, s0 * y1 );
  871. // bottom cap
  872. *pOut++ = Vector( -x0 * m_flRadius, c1 * y0, s1 * y0 );
  873. *pOut++ = Vector( -x1 * m_flRadius, c1 * y1, s1 * y1 );
  874. *pOut++ = Vector( -x0 * m_flRadius, c0 * y0, s0 * y0 );
  875. *pOut++ = Vector( -x1 * m_flRadius, c1 * y1, s1 * y1 );
  876. *pOut++ = Vector( -x1 * m_flRadius, c0 * y1, s0 * y1 );
  877. *pOut++ = Vector( -x0 * m_flRadius, c0 * y0, s0 * y0 );
  878. x0 = x1;
  879. y0 = y1;
  880. }
  881. // the end of caps
  882. *pOut++ = Vector( -m_flRadius, 0, 0 );
  883. *pOut++ = Vector( -x1 * m_flRadius, c0 * y1, s0 * y1 );
  884. *pOut++ = Vector( -x1 * m_flRadius, c1 * y1, s1 * y1 );
  885. *pOut++ = Vector( flHeight + m_flRadius, 0, 0 );
  886. *pOut++ = Vector( flHeight + x1 * m_flRadius, c1 * y1, s1 * y1 );
  887. *pOut++ = Vector( flHeight + x1 * m_flRadius, c0 * y1, s0 * y1 );
  888. s0 = s1;
  889. c0 = c1;
  890. }
  891. for( Vector *p = pVerts; p < pOut; ++p )
  892. {
  893. *p = m_vCenter[0] + vAxisX * p->x + vAxisY * p->y + vAxisZ * p->z;
  894. }
  895. Assert( nSides * ( 2 + 2 * ( 2 * nSlices + 1 ) ) * 3 == pOut - pVerts );
  896. }
  897. return nSides * ( 2 + 2 * ( 2 * nSlices + 1 ) ) * 3; // each side is 4 tris, each 3 verts
  898. }
  899. //--------------------------------------------------------------------------------------------------
  900. inline void RnCapsule_t::GetTriangulation( CUtlVector<Vector> &vertices, CUtlVector<uint32> &indices )const
  901. {
  902. GetTriangulation( vertices, indices, 12, 2 );
  903. }
  904. //--------------------------------------------------------------------------------------------------
  905. inline void RnCapsule_t::GetTriangulation( CUtlVector<Vector> &vertices, CUtlVector<uint32> &indices, int nSides, int nSlices )const
  906. {
  907. int nVertBase = vertices.Count();
  908. int nIndexBase = indices.AddMultipleToTail( nSides * ( 2 + 2 * ( 2 * nSlices + 1 ) ) * 3 ); // each side is 4 tris, each 3 verts
  909. uint32 *pOut = &indices[ nIndexBase ];
  910. int nSideVerts = 2 + 2 * nSlices;
  911. vertices.AddMultipleToTail( nSides * nSideVerts + 2 );
  912. Vector *pVerts = &vertices[nVertBase];
  913. V_memset( pVerts, 0, nSides * nSideVerts * sizeof( Vector ) );
  914. Vector vHeight = m_vCenter[1] - m_vCenter[0];
  915. float flHeight = vHeight.Length();
  916. Vector vAxisX;
  917. if( flHeight > 1e-5f )
  918. {
  919. vAxisX = vHeight / flHeight;
  920. }
  921. else
  922. {
  923. vAxisX = vHeight = Vector( 1,0,0 );
  924. flHeight = 1;
  925. }
  926. Vector vAxisY = VectorPerpendicularToVector( vAxisX ), vAxisZ = CrossProduct( vAxisX, vAxisY );
  927. pVerts[ nSides * nSideVerts + 0 ] = Vector( -m_flRadius, 0, 0 );
  928. pVerts[ nSides * nSideVerts + 1 ] = Vector( flHeight + m_flRadius, 0, 0 );
  929. for( int i = 0; i < nSides; ++i )
  930. {
  931. float theta = ( -2 * M_PI * i ) / nSides;
  932. float s0 = m_flRadius * sinf( theta ), c0 = m_flRadius * cosf( theta );
  933. int i1 = ( i + 1 ) % nSides;
  934. // cylinder sides
  935. *pOut++ = nVertBase + nSideVerts * i1;
  936. *pOut++ = nVertBase + nSideVerts * i;
  937. *pOut++ = nVertBase + nSideVerts * i1 + 1;
  938. *pOut++ = nVertBase + nSideVerts * i1 + 1;
  939. *pOut++ = nVertBase + nSideVerts * i;
  940. *pOut++ = nVertBase + nSideVerts * i + 1;
  941. // caps - quads
  942. for( int j = 0; ; ++j )
  943. {
  944. int j1 = j + 1;
  945. float psi = ( j * M_PI / 2 ) / ( nSlices + 1 ), x0 = sinf( psi ), y0 = cosf( psi );
  946. pVerts[nSideVerts * i + j * 2 + 0 ] = Vector( - x0 * m_flRadius, c0 * y0, s0 * y0 );
  947. pVerts[nSideVerts * i + j * 2 + 1 ] = Vector( flHeight + x0 * m_flRadius, c0 * y0, s0 * y0 );
  948. if( j < nSlices)
  949. {
  950. // top cap
  951. *pOut++ = nVertBase + nSideVerts * i1 + j * 2 + 1;
  952. *pOut++ = nVertBase + nSideVerts * i + j * 2 + 1;
  953. *pOut++ = nVertBase + nSideVerts * i1 + j1 * 2 + 1;
  954. *pOut++ = nVertBase + nSideVerts * i1 + j1 * 2 + 1;
  955. *pOut++ = nVertBase + nSideVerts * i + j * 2 + 1;
  956. *pOut++ = nVertBase + nSideVerts * i + j1 * 2 + 1;
  957. // bottom cap
  958. *pOut++ = nVertBase + nSideVerts * i1 + j * 2 + 0;
  959. *pOut++ = nVertBase + nSideVerts * i1 + j1 * 2 + 0;
  960. *pOut++ = nVertBase + nSideVerts * i + j * 2 + 0;
  961. *pOut++ = nVertBase + nSideVerts * i1 + j1 * 2 + 0;
  962. *pOut++ = nVertBase + nSideVerts * i + j1 * 2 + 0;
  963. *pOut++ = nVertBase + nSideVerts * i + j * 2 + 0;
  964. }
  965. else
  966. {
  967. // the last slice - only triangles
  968. // the end of caps
  969. *pOut++ = nVertBase + nSides * nSideVerts + 0;
  970. *pOut++ = nVertBase + nSideVerts * i + j * 2 + 0;
  971. *pOut++ = nVertBase + nSideVerts * i1 + j * 2 + 0;
  972. *pOut++ = nVertBase + nSides * nSideVerts + 1;
  973. *pOut++ = nVertBase + nSideVerts * i1 + j * 2 + 1;
  974. *pOut++ = nVertBase + nSideVerts * i + j * 2 + 1;
  975. break;
  976. }
  977. }
  978. }
  979. for( int i = 0; i < nSides * nSideVerts + 2; ++i )
  980. {
  981. pVerts[i] = m_vCenter[0] + vAxisX * pVerts[i].x + vAxisY * pVerts[i].y + vAxisZ * pVerts[i].z;
  982. }
  983. Assert( pOut == indices.end() );
  984. AssertDbg( IsTriangulationValid( vertices, indices ) );
  985. }
  986. //--------------------------------------------------------------------------------------------------
  987. inline AABB_t RnHull_t::GetBbox() const
  988. {
  989. // note: we should store the bbox in RnHull if it's a frequent operation to compute its bbox
  990. AABB_t b;
  991. b.MakeInvalid();
  992. for( int nVert = 0; nVert < m_Vertices.Count(); ++nVert )
  993. {
  994. b |= m_Vertices[nVert];
  995. }
  996. return b;
  997. }
  998. //--------------------------------------------------------------------------------------------------
  999. inline AABB_t RnHull_t::GetBbox( const CTransform& xform ) const
  1000. {
  1001. // note: if we store the bbox in RnHull we could just transform it (which potentially might grow it)
  1002. AABB_t b;
  1003. b.MakeInvalid();
  1004. for ( int nVert = 0; nVert < m_Vertices.Count(); ++nVert )
  1005. {
  1006. b |= TransformPoint( xform, m_Vertices[ nVert ] );
  1007. }
  1008. return b;
  1009. }
  1010. //--------------------------------------------------------------------------------------------------
  1011. inline int RnHull_t::GetTriangulation( Vector *pVerts ) const
  1012. {
  1013. int nVertsOut = 0;
  1014. for( int nFace = 0; nFace < m_Faces.Count(); ++nFace )
  1015. {
  1016. uint nStartEdge = m_Faces[nFace].m_nEdge, nStartVert = m_Edges[nStartEdge].m_nOrigin;
  1017. const Vector &vStartEdge = m_Vertices[ nStartVert ];
  1018. for( uint nEdge = m_Edges[nStartEdge].m_nNext; nEdge != nStartEdge; )
  1019. {
  1020. uint nNextEdge = m_Edges[nEdge].m_nNext; // go to next edge
  1021. if( nNextEdge == nStartEdge )
  1022. {
  1023. break; // if next edge is the starting edge, we're done
  1024. }
  1025. if( pVerts )
  1026. {
  1027. pVerts[ nVertsOut + 0 ] = vStartEdge;
  1028. pVerts[ nVertsOut + 1 ] = m_Vertices[ m_Edges[nEdge].m_nOrigin ];
  1029. pVerts[ nVertsOut + 2 ] = m_Vertices[ m_Edges[nNextEdge].m_nOrigin ];
  1030. }
  1031. nVertsOut += 3;
  1032. nEdge = nNextEdge;
  1033. }
  1034. }
  1035. return nVertsOut;
  1036. }
  1037. //------------------------------------------------------------------------------------------------------------------------------------------------------
  1038. inline void RnHull_t::GetTriangulation( CUtlVector<Vector> &vertices, CUtlVector<uint32> &indices, float flScale )const
  1039. {
  1040. int nVertBase = vertices.Count();
  1041. vertices.AddMultipleToTail( GetVertexCount() );
  1042. for( int i = 0; i < GetVertexCount(); ++i )
  1043. {
  1044. vertices[ i + nVertBase ] = GetVertex( i ) * flScale;
  1045. }
  1046. for ( int i = 0; i < GetFaceCount(); ++i )
  1047. {
  1048. const RnFace_t* pFace = GetFace( i );
  1049. const RnHalfEdge_t* pEdge1 = GetEdge( pFace->m_nEdge );
  1050. const RnHalfEdge_t* pEdge2 = GetEdge( pEdge1->m_nNext );
  1051. const RnHalfEdge_t* pEdge3 = GetEdge( pEdge2->m_nNext );
  1052. AssertDbg( pEdge1 != pEdge3 );
  1053. int v1 = nVertBase + pEdge1->m_nOrigin;
  1054. do
  1055. {
  1056. int v2 = nVertBase + pEdge2->m_nOrigin;
  1057. int v3 = nVertBase + pEdge3->m_nOrigin;
  1058. indices.AddToTail( v1 );
  1059. indices.AddToTail( v2 );
  1060. indices.AddToTail( v3 );
  1061. pEdge2 = pEdge3;
  1062. pEdge3 = GetEdge( pEdge3->m_nNext );
  1063. }
  1064. while ( pEdge1 != pEdge3 );
  1065. }
  1066. AssertDbg( IsTriangulationValid( vertices, indices ) );
  1067. }
  1068. //--------------------------------------------------------------------------------------------------
  1069. inline AABB_t RnMesh_t::GetBbox()const
  1070. {
  1071. AABB_t b;
  1072. b.m_vMinBounds = m_vMin;
  1073. b.m_vMaxBounds = m_vMax;
  1074. return b;
  1075. }
  1076. //------------------------------------------------------------------------------------------------------------------------------------------------------
  1077. inline int RnMesh_t::GetTriangulation( Vector *pVerts ) const
  1078. {
  1079. if( pVerts )
  1080. {
  1081. for( int nTriangleIndex = 0; nTriangleIndex < m_Triangles.Count(); ++nTriangleIndex )
  1082. {
  1083. const RnTriangle_t &tri = m_Triangles[nTriangleIndex];
  1084. for( int nVertInTri = 0; nVertInTri < 3; ++nVertInTri )
  1085. {
  1086. pVerts[ nTriangleIndex * 3 + nVertInTri ] = m_Vertices[ tri.m_nIndex[ nVertInTri ] ];
  1087. }
  1088. }
  1089. }
  1090. return m_Triangles.Count() * 3;
  1091. }
  1092. //------------------------------------------------------------------------------------------------------------------------------------------------------
  1093. inline void RnMesh_t::GetTriangulation( CUtlVector<Vector> &vertices, CUtlVector<uint32> &indices, const Vector &vScale ) const
  1094. {
  1095. int nVertBase = vertices.Count();
  1096. vertices.AddMultipleToTail( GetVertexCount() );
  1097. for ( int i = 0; i < GetVertexCount(); ++i )
  1098. {
  1099. Vector vertex = vScale * GetVertex( i );
  1100. vertices[ nVertBase + i ] = vertex;
  1101. }
  1102. indices.EnsureCapacity( 3 * GetTriangleCount() );
  1103. for ( int i = 0; i < GetTriangleCount(); ++i )
  1104. {
  1105. const RnTriangle_t* pTriangle = GetTriangle( i );
  1106. indices.AddToTail( nVertBase + pTriangle->m_nIndex[ 0 ] );
  1107. indices.AddToTail( nVertBase + pTriangle->m_nIndex[ 1 ] );
  1108. indices.AddToTail( nVertBase + pTriangle->m_nIndex[ 2 ] );
  1109. }
  1110. AssertDbg( IsTriangulationValid( vertices, indices ) );
  1111. }
  1112. //------------------------------------------------------------------------------------------------------------------------------------------------------
  1113. inline float RnSphere_t::GetVolume()const
  1114. {
  1115. return m_flRadius * m_flRadius * m_flRadius * M_PI * ( 4.0f / 3.0f ); // http://en.wikipedia.org/wiki/Sphere#Volume_of_a_sphere
  1116. }
  1117. //------------------------------------------------------------------------------------------------------------------------------------------------------
  1118. inline float RnCapsule_t::GetVolume()const
  1119. {
  1120. return m_flRadius * m_flRadius * M_PI * ( m_flRadius * ( 4.0f / 3.0f ) + ( m_vCenter[0] - m_vCenter[1] ).Length() ); // http://en.wikipedia.org/wiki/Sphere#Volume_of_a_sphere
  1121. }
  1122. //------------------------------------------------------------------------------------------------------------------------------------------------------
  1123. inline float RnHull_t::GetVolume()const
  1124. {
  1125. float flVolume = 0;
  1126. for( int nFace = 0; nFace < m_Faces.Count(); ++nFace )
  1127. {
  1128. uint nStartEdge = m_Faces[nFace].m_nEdge, nStartVert = m_Edges[nStartEdge].m_nOrigin;
  1129. const Vector &vStartEdge = m_Vertices[ nStartVert ];
  1130. for( uint nEdge = m_Edges[nStartEdge].m_nNext; nEdge != nStartEdge; )
  1131. {
  1132. uint nNextEdge = m_Edges[nEdge].m_nNext; // go to next edge
  1133. if( nNextEdge == nStartEdge )
  1134. {
  1135. break; // if next edge is the starting edge, we're done
  1136. }
  1137. Vector v1 = m_Vertices[ m_Edges[nEdge].m_nOrigin ];
  1138. Vector v2 = m_Vertices[ m_Edges[nNextEdge].m_nOrigin ];
  1139. float flCenterZHalf = ( vStartEdge.z + v1.z + v2.z ) * ( 1.0f / 6.0f ); // half-height of the prism, to account for cross product being double the area of base
  1140. float flSignedDoubleBaseArea = CrossProductZ( v1 - vStartEdge, v2 - vStartEdge );
  1141. flVolume += flCenterZHalf * flSignedDoubleBaseArea;
  1142. nEdge = nNextEdge;
  1143. }
  1144. }
  1145. Assert( flVolume > 0 );
  1146. return flVolume;
  1147. }
  1148. FORCEINLINE const Vector RnMesh_t::ComputeTriangleUnitNormal( const Vector &vScale, int nTriIndex )const
  1149. {
  1150. const RnTriangle_t* pTriangle = GetTriangle( nTriIndex );
  1151. const Vector& vVertex1 = GetVertex( pTriangle->m_nIndex[ 0 ] );
  1152. const Vector& vVertex2 = GetVertex( pTriangle->m_nIndex[ 1 ] );
  1153. const Vector& vVertex3 = GetVertex( pTriangle->m_nIndex[ 2 ] );
  1154. Vector vEdge1 = ScaleVector( vScale, vVertex2 - vVertex1 );
  1155. Vector vEdge2 = ScaleVector( vScale, vVertex3 - vVertex1 );
  1156. Vector vNormal = CrossProduct( vEdge1, vEdge2 );
  1157. return vNormal / vNormal.Length(); // valid RnMesh should never have degenerate triangles
  1158. }
  1159. FORCEINLINE const Vector RnMesh_t::ComputeTriangleCentroid( int nTriIndex )const
  1160. {
  1161. const RnTriangle_t* pTriangle = GetTriangle( nTriIndex );
  1162. const Vector& vVertex1 = GetVertex( pTriangle->m_nIndex[ 0 ] );
  1163. const Vector& vVertex2 = GetVertex( pTriangle->m_nIndex[ 1 ] );
  1164. const Vector& vVertex3 = GetVertex( pTriangle->m_nIndex[ 2 ] );
  1165. return ( vVertex1 + vVertex2 + vVertex3 ) * ( 1.0f / 3.0f );
  1166. }
  1167. FORCEINLINE const Vector RnMesh_t::ComputeTriangleIncenter( int nTriIndex )const
  1168. {
  1169. const RnTriangle_t* pTriangle = GetTriangle( nTriIndex );
  1170. const Vector& a = GetVertex( pTriangle->m_nIndex[ 0 ] );
  1171. const Vector& b = GetVertex( pTriangle->m_nIndex[ 1 ] );
  1172. const Vector& c = GetVertex( pTriangle->m_nIndex[ 2 ] );
  1173. float la = ( b - c ).Length(), lb = ( a - c ).Length(), lc = ( b - a ).Length();
  1174. return ( a * la + b * lb + c * lc ) / ( la + lb + lc );
  1175. }
  1176. FORCEINLINE const Vector RnHull_t::ComputeFaceCentroid( int nFace )const
  1177. {
  1178. Vector vSum( 0,0,0 );
  1179. uint8 nFirstEdge = m_Faces[nFace].m_nEdge, nEdge = nFirstEdge;
  1180. float flNumEdges = 0;
  1181. do
  1182. {
  1183. AssertDbg( m_Edges[nEdge].m_nFace == uint( nFace ) );
  1184. vSum += m_Vertices[ m_Edges[nEdge].m_nOrigin ];
  1185. nEdge = m_Edges[ nEdge ].m_nNext;
  1186. flNumEdges += 1.0f;
  1187. } while ( nEdge != nFirstEdge );
  1188. return vSum / flNumEdges;
  1189. }
  1190. //--------------------------------------------------------------------------------------------------
  1191. // SIMD clipping
  1192. //--------------------------------------------------------------------------------------------------
  1193. FORCEINLINE fltx4 HMaxSIMD( fltx4 a )
  1194. {
  1195. fltx4 b = RotateLeft( a );
  1196. fltx4 c = MaxSIMD( a, b );
  1197. fltx4 d = RotateLeft2( c );
  1198. return MaxSIMD( c, d );
  1199. }
  1200. //-------------------------------------------------------------------------------------------------
  1201. FORCEINLINE fltx4 HMinSIMD( fltx4 a )
  1202. {
  1203. fltx4 b = RotateLeft( a );
  1204. fltx4 c = MinSIMD( a, b );
  1205. fltx4 d = RotateLeft2( c );
  1206. return MinSIMD( c, d );
  1207. }
  1208. //-------------------------------------------------------------------------------------------------
  1209. FORCEINLINE int ClipRaySIMD( const RnRay_t& ray, const Vector& vMin, const Vector& vMax, float &flBestTime )
  1210. {
  1211. fltx4 f4Min = LoadAlignedSIMD( &vMin.x ), f4Max = LoadAlignedSIMD( &vMax.x );
  1212. fltx4 f4Origin = LoadAlignedSIMD( &ray.vOrigin ), f4DeltaInv = LoadAlignedSIMD( &ray.vDeltaInv );
  1213. fltx4 t1 = ( f4Min - f4Origin ) * f4DeltaInv; // can be MADD
  1214. fltx4 t2 = ( f4Max - f4Origin ) * f4DeltaInv; // can be MADD
  1215. fltx4 f4TMin = MinSIMD( t1, t2 ), f4TMax = MaxSIMD( t1, t2 );
  1216. fltx4 f4MinT = HMaxSIMD( SetWSIMD( f4TMin, Four_Zeros ) );
  1217. fltx4 f4MaxT = HMinSIMD( SetWSIMD( f4TMax, ReplicateX4( flBestTime ) ) );
  1218. // flMinT = max( 0, f4TMin.xyz )
  1219. // flMaxT = min( 1, f4TMin.xyz )
  1220. // return ( flMinT > flMaxT || flMinT > flBestTime )
  1221. return _mm_comigt_ss( f4MinT, f4MaxT );
  1222. }
  1223. //-------------------------------------------------------------------------------------------------
  1224. FORCEINLINE int ClipRaySIMD( const RnRay_t& ray, const fltx4 &f4Min , const fltx4& f4Max, float &flBestTime )
  1225. {
  1226. fltx4 f4Origin = LoadAlignedSIMD( &ray.vOrigin ), f4DeltaInv = LoadAlignedSIMD( &ray.vDeltaInv );
  1227. fltx4 t1 = ( f4Min - f4Origin ) * f4DeltaInv; // can be MADD
  1228. fltx4 t2 = ( f4Max - f4Origin ) * f4DeltaInv; // can be MADD
  1229. fltx4 f4TMin = MinSIMD( t1, t2 ), f4TMax = MaxSIMD( t1, t2 );
  1230. fltx4 f4MinT = HMaxSIMD( SetWSIMD( f4TMin, Four_Zeros ) );
  1231. fltx4 f4MaxT = HMinSIMD( SetWSIMD( f4TMax, ReplicateX4( flBestTime ) ) );
  1232. // flMinT = max( 0, f4TMin.xyz )
  1233. // flMaxT = min( 1, f4TMin.xyz )
  1234. // return ( flMinT > flMaxT || flMinT > flBestTime )
  1235. return _mm_comigt_ss( f4MinT, f4MaxT );
  1236. }
  1237. //-------------------------------------------------------------------------------------------------
  1238. FORCEINLINE int ClipRaySIMD( const RnRay_t& ray, const fltx4& f4Min, const fltx4& f4Max )
  1239. {
  1240. fltx4 f4Origin = LoadAlignedSIMD( &ray.vOrigin ), f4DeltaInv = LoadAlignedSIMD( &ray.vDeltaInv );
  1241. fltx4 t1 = ( f4Min - f4Origin ) * f4DeltaInv; // can be MADD
  1242. fltx4 t2 = ( f4Max - f4Origin ) * f4DeltaInv; // can be MADD
  1243. fltx4 f4TMin = MinSIMD( t1, t2 ), f4TMax = MaxSIMD( t1, t2 );
  1244. fltx4 f4MinT = HMaxSIMD( SetWSIMD( f4TMin, Four_Zeros ) );
  1245. fltx4 f4MaxT = HMinSIMD( SetWSIMD( f4TMax, Four_Ones ) );
  1246. // flMinT = max( 0, f4TMin.xyz )
  1247. // flMaxT = min( 1, f4TMin.xyz )
  1248. // return ( flMinT > flMaxT || flMinT > flBestTime )
  1249. return _mm_comigt_ss( f4MinT, f4MaxT );
  1250. }
  1251. //-------------------------------------------------------------------------------------------------
  1252. template < typename Functor >
  1253. void RnMesh_t::CastBox( const Functor &callback, const RnRay_t &ray, const Vector& vLocalExtent, float flMaxFraction ) const
  1254. {
  1255. int nCount = 0;
  1256. const RnNode_t* stack[ STACK_SIZE ];
  1257. stack[ nCount++ ] = GetRoot();
  1258. fltx4 f4LocalExtent = LoadUnalignedSIMD( &vLocalExtent );
  1259. while ( nCount > 0 )
  1260. {
  1261. const RnNode_t* pNode = stack[ --nCount ];
  1262. if( ClipRaySIMD( ray, LoadAlignedSIMD( &pNode->m_vMin ) - f4LocalExtent, LoadAlignedSIMD( &pNode->m_vMax ) + f4LocalExtent ) )
  1263. {
  1264. continue;
  1265. }
  1266. if ( !pNode->IsLeaf() )
  1267. {
  1268. // Determine traversal order (front -> back)
  1269. // The near and far child are determined by the direction of
  1270. // the ray with respect to the dimension of the split plane.
  1271. const RnNode_t *pLeft = pNode->GetLeftChild(), *pRight = pNode->GetRightChild();
  1272. if ( ray.vDelta[ pNode->GetAxis() ] > 0.0f )
  1273. {
  1274. stack[ nCount++ ] = pRight;
  1275. stack[ nCount++ ] = pLeft;
  1276. }
  1277. else
  1278. {
  1279. stack[ nCount++ ] = pLeft;
  1280. stack[ nCount++ ] = pRight;
  1281. }
  1282. AssertDbg( nCount < STACK_SIZE - 1 ); // there should always be space for at least 1 more entry in the stack
  1283. }
  1284. else
  1285. {
  1286. uint32 nTriangleCount = pNode->GetTriangleCount();
  1287. uint32 nTriangleOffset = pNode->GetTriangleOffset();
  1288. for ( uint32 nTriangle = 0; nTriangle < nTriangleCount; ++nTriangle )
  1289. {
  1290. // Get the triangle in world coordinates
  1291. const RnTriangle_t* pTriangle = GetTriangle( nTriangleOffset + nTriangle );
  1292. const Vector &vVertex1 = GetVertex( pTriangle->m_nIndex[ 0 ] );
  1293. const Vector &vVertex2 = GetVertex( pTriangle->m_nIndex[ 1 ] );
  1294. const Vector &vVertex3 = GetVertex( pTriangle->m_nIndex[ 2 ] );
  1295. callback( vVertex1, vVertex2, vVertex3 );
  1296. }
  1297. }
  1298. }
  1299. }
  1300. template <typename Array>
  1301. inline bool ArePlainArraysEqual( const Array &a, const Array &b )
  1302. {
  1303. return a.Count( ) == b.Count( ) && 0 == V_memcmp( a.Base( ), b.Base( ), a.Count( ) * sizeof( a[ 0 ] ) );
  1304. }
  1305. template <typename Array>
  1306. inline void CRC64_ProcessArray( CRC64_t *pCrc, const Array &array )
  1307. {
  1308. CRC64_ProcessBuffer( pCrc, array.Base( ), array.Count( ) * sizeof( array[ 0 ] ) );
  1309. }
  1310. class CRnEqualFunctor
  1311. {
  1312. public:
  1313. bool operator() ( const RnHull_t *pLeft, const RnHull_t *pRight )const
  1314. {
  1315. return ArePlainArraysEqual( pLeft->m_Vertices, pRight->m_Vertices )
  1316. && ArePlainArraysEqual( pLeft->m_Planes, pRight->m_Planes )
  1317. && ArePlainArraysEqual( pLeft->m_Edges, pRight->m_Edges )
  1318. && ArePlainArraysEqual( pLeft->m_Faces, pRight->m_Faces );
  1319. }
  1320. bool operator() ( const RnMesh_t *pLeft, const RnMesh_t *pRight )const
  1321. {
  1322. return ArePlainArraysEqual( pLeft->m_Vertices, pRight->m_Vertices )
  1323. && ArePlainArraysEqual( pLeft->m_Nodes, pRight->m_Nodes )
  1324. && ArePlainArraysEqual( pLeft->m_Triangles, pRight->m_Triangles )
  1325. && ArePlainArraysEqual( pLeft->m_Materials, pRight->m_Materials );
  1326. }
  1327. };
  1328. class CRnHashFunctor
  1329. {
  1330. public:
  1331. uint operator()( const RnHull_t *pHull )const
  1332. {
  1333. CRC64_t nCrc;
  1334. CRC64_Init( &nCrc );
  1335. CRC64_ProcessArray( &nCrc, pHull->m_Vertices );
  1336. CRC64_ProcessArray( &nCrc, pHull->m_Planes );
  1337. CRC64_ProcessArray( &nCrc, pHull->m_Edges );
  1338. CRC64_ProcessArray( &nCrc, pHull->m_Faces );
  1339. CRC64_Final( &nCrc );
  1340. return nCrc;
  1341. }
  1342. uint operator()( const RnMesh_t *pHull )const
  1343. {
  1344. CRC64_t nCrc;
  1345. CRC64_Init( &nCrc );
  1346. CRC64_ProcessArray( &nCrc, pHull->m_Vertices );
  1347. CRC64_ProcessArray( &nCrc, pHull->m_Nodes );
  1348. CRC64_ProcessArray( &nCrc, pHull->m_Triangles );
  1349. CRC64_ProcessArray( &nCrc, pHull->m_Materials );
  1350. CRC64_Final( &nCrc );
  1351. return nCrc;
  1352. }
  1353. };
  1354. #endif