pxCollision.cpp 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "platform/platform.h"
  23. #include "T3D/physics/physX/pxCollision.h"
  24. #include "math/mPoint3.h"
  25. #include "math/mMatrix.h"
  26. #include "T3D/physics/physX/px.h"
  27. #include "T3D/physics/physX/pxCasts.h"
  28. #include "T3D/physics/physX/pxWorld.h"
  29. #include "T3D/physics/physX/pxStream.h"
  30. PxCollision::PxCollision()
  31. {
  32. }
  33. PxCollision::~PxCollision()
  34. {
  35. // We may be deleteting SDK data... so make
  36. // sure we have the the scene write lock.
  37. PxWorld::releaseWriteLocks();
  38. for ( U32 i=0; i < mColShapes.size(); i++ )
  39. {
  40. // Check for special types which need cleanup.
  41. NxShapeDesc *desc = mColShapes[i];
  42. if ( desc->getType() == NX_SHAPE_CONVEX )
  43. gPhysicsSDK->releaseConvexMesh( *((NxConvexShapeDesc*)desc)->meshData );
  44. else if ( desc->getType() == NX_SHAPE_MESH )
  45. gPhysicsSDK->releaseTriangleMesh( *((NxTriangleMeshShapeDesc*)desc)->meshData );
  46. else if ( desc->getType() == NX_SHAPE_HEIGHTFIELD )
  47. gPhysicsSDK->releaseHeightField( *((NxHeightFieldShapeDesc*)desc)->heightField );
  48. // Delete the descriptor.
  49. delete desc;
  50. }
  51. mColShapes.clear();
  52. }
  53. void PxCollision::addPlane( const PlaneF &plane )
  54. {
  55. NxBoxShapeDesc *desc = new NxBoxShapeDesc;
  56. desc->skinWidth = 0.01f;
  57. desc->dimensions.set( 10000.0f, 10000.0f, 100.0f );
  58. desc->localPose.t.z = -100.0f;
  59. // TODO: Fix rotation to match plane normal!
  60. //boxDesc->localPose.M.setColumn( 0, NxVec3( plane.x, plane.y, plane.z ) );
  61. //boxDesc->localPose.M.setColumn( 1, NxVec3( plane.x, plane.y, plane.z ) );
  62. //boxDesc->localPose.M.setColumn( 2, NxVec3( plane.x, plane.y, plane.z ) );
  63. mColShapes.push_back( desc );
  64. }
  65. void PxCollision::addBox( const Point3F &halfWidth,
  66. const MatrixF &localXfm )
  67. {
  68. NxBoxShapeDesc *desc = new NxBoxShapeDesc;
  69. desc->skinWidth = 0.01f;
  70. desc->dimensions.set( halfWidth.x, halfWidth.y, halfWidth.z );
  71. desc->localPose.setRowMajor44( localXfm );
  72. mColShapes.push_back( desc );
  73. }
  74. void PxCollision::addSphere( F32 radius,
  75. const MatrixF &localXfm )
  76. {
  77. NxSphereShapeDesc *desc = new NxSphereShapeDesc;
  78. desc->skinWidth = 0.01f;
  79. desc->radius = radius;
  80. desc->localPose.setRowMajor44( localXfm );
  81. mColShapes.push_back( desc );
  82. }
  83. void PxCollision::addCapsule( F32 radius,
  84. F32 height,
  85. const MatrixF &localXfm )
  86. {
  87. NxCapsuleShapeDesc *desc = new NxCapsuleShapeDesc;
  88. desc->skinWidth = 0.01f;
  89. desc->radius = radius;
  90. desc->height = height;
  91. desc->localPose.setRowMajor44( localXfm );
  92. mColShapes.push_back( desc );
  93. }
  94. bool PxCollision::addConvex( const Point3F *points,
  95. U32 count,
  96. const MatrixF &localXfm )
  97. {
  98. // Mesh cooking requires that both
  99. // scenes not be write locked!
  100. PxWorld::releaseWriteLocks();
  101. NxCookingInterface *cooker = PxWorld::getCooking();
  102. cooker->NxInitCooking();
  103. NxConvexMeshDesc meshDesc;
  104. meshDesc.numVertices = count;
  105. meshDesc.pointStrideBytes = sizeof(Point3F);
  106. meshDesc.points = points;
  107. meshDesc.flags = NX_CF_COMPUTE_CONVEX | NX_CF_INFLATE_CONVEX;
  108. // Cook it!
  109. NxCookingParams params;
  110. #ifdef TORQUE_OS_XENON
  111. params.targetPlatform = PLATFORM_XENON;
  112. #else
  113. params.targetPlatform = PLATFORM_PC;
  114. #endif
  115. params.skinWidth = 0.01f;
  116. params.hintCollisionSpeed = true;
  117. cooker->NxSetCookingParams( params );
  118. PxMemStream stream;
  119. bool cooked = cooker->NxCookConvexMesh( meshDesc, stream );
  120. cooker->NxCloseCooking();
  121. if ( !cooked )
  122. return false;
  123. stream.resetPosition();
  124. NxConvexMesh *meshData = gPhysicsSDK->createConvexMesh( stream );
  125. if ( !meshData )
  126. return false;
  127. NxConvexShapeDesc *desc = new NxConvexShapeDesc;
  128. desc->skinWidth = 0.01f;
  129. desc->meshData = meshData;
  130. desc->localPose.setRowMajor44( localXfm );
  131. mColShapes.push_back( desc );
  132. return true;
  133. }
  134. bool PxCollision::addTriangleMesh( const Point3F *vert,
  135. U32 vertCount,
  136. const U32 *index,
  137. U32 triCount,
  138. const MatrixF &localXfm )
  139. {
  140. // Mesh cooking requires that both
  141. // scenes not be write locked!
  142. PxWorld::releaseWriteLocks();
  143. NxCookingInterface *cooker = PxWorld::getCooking();
  144. cooker->NxInitCooking();
  145. NxTriangleMeshDesc meshDesc;
  146. meshDesc.numVertices = vertCount;
  147. meshDesc.numTriangles = triCount;
  148. meshDesc.pointStrideBytes = sizeof(Point3F);
  149. meshDesc.triangleStrideBytes = 3*sizeof(U32);
  150. meshDesc.points = vert;
  151. meshDesc.triangles = index;
  152. meshDesc.flags = NX_MF_FLIPNORMALS;
  153. // Cook it!
  154. NxCookingParams params;
  155. #ifdef TORQUE_OS_XENON
  156. params.targetPlatform = PLATFORM_XENON;
  157. #else
  158. params.targetPlatform = PLATFORM_PC;
  159. #endif
  160. params.skinWidth = 0.01f;
  161. params.hintCollisionSpeed = true;
  162. cooker->NxSetCookingParams( params );
  163. PxMemStream stream;
  164. bool cooked = cooker->NxCookTriangleMesh( meshDesc, stream );
  165. cooker->NxCloseCooking();
  166. if ( !cooked )
  167. return false;
  168. stream.resetPosition();
  169. NxTriangleMesh *meshData = gPhysicsSDK->createTriangleMesh( stream );
  170. if ( !meshData )
  171. return false;
  172. NxTriangleMeshShapeDesc *desc = new NxTriangleMeshShapeDesc;
  173. desc->skinWidth = 0.01f;
  174. desc->meshData = meshData;
  175. desc->localPose.setRowMajor44( localXfm );
  176. mColShapes.push_back( desc );
  177. return true;
  178. }
  179. bool PxCollision::addHeightfield( const U16 *heights,
  180. const bool *holes,
  181. U32 blockSize,
  182. F32 metersPerSample,
  183. const MatrixF &localXfm )
  184. {
  185. // Since we're creating SDK level data we
  186. // have to have access to all active worlds.
  187. PxWorld::releaseWriteLocks();
  188. // Init the heightfield description.
  189. NxHeightFieldDesc heightFieldDesc;
  190. heightFieldDesc.nbColumns = blockSize;
  191. heightFieldDesc.nbRows = blockSize;
  192. heightFieldDesc.thickness = -10.0f;
  193. heightFieldDesc.convexEdgeThreshold = 0;
  194. // Allocate the samples.
  195. heightFieldDesc.samples = new NxU32[ blockSize * blockSize ];
  196. heightFieldDesc.sampleStride = sizeof(NxU32);
  197. NxU8 *currentByte = (NxU8*)heightFieldDesc.samples;
  198. for ( U32 row = 0; row < blockSize; row++ )
  199. {
  200. const U32 tess = ( row + 1 ) % 2;
  201. for ( U32 column = 0; column < blockSize; column++ )
  202. {
  203. NxHeightFieldSample *currentSample = (NxHeightFieldSample*)currentByte;
  204. U32 index = ( blockSize - row - 1 ) + ( column * blockSize );
  205. currentSample->height = heights[ index ];
  206. if ( holes && holes[ getMax( (S32)index - 1, 0 ) ] ) // row index for holes adjusted so PhysX collision shape better matches rendered terrain
  207. {
  208. currentSample->materialIndex0 = 0;
  209. currentSample->materialIndex1 = 0;
  210. }
  211. else
  212. {
  213. currentSample->materialIndex0 = 1; //materialIds[0];
  214. currentSample->materialIndex1 = 1; //materialIds[0];
  215. }
  216. currentSample->tessFlag = ( column + tess ) % 2;
  217. currentByte += heightFieldDesc.sampleStride;
  218. }
  219. }
  220. // Build it.
  221. NxHeightFieldShapeDesc *desc = new NxHeightFieldShapeDesc;
  222. desc->heightField = gPhysicsSDK->createHeightField( heightFieldDesc );
  223. // Destroy the temp sample array.
  224. delete [] heightFieldDesc.samples;
  225. // TerrainBlock uses a 11.5 fixed point height format
  226. // giving it a maximum height range of 0 to 2048.
  227. desc->heightScale = 0.03125f;
  228. desc->rowScale = metersPerSample;
  229. desc->columnScale = metersPerSample;
  230. desc->materialIndexHighBits = 0;
  231. desc->skinWidth = 0.01f;
  232. // Use the local pose to align the heightfield
  233. // to what Torque will expect.
  234. NxMat33 rotX;
  235. rotX.rotX( Float_HalfPi );
  236. NxMat33 rotZ;
  237. rotZ.rotZ( Float_Pi );
  238. NxMat34 rot;
  239. rot.M.multiply( rotZ, rotX );
  240. rot.t.set( ( blockSize - 1 ) * metersPerSample, 0, 0 );
  241. desc->localPose = rot;
  242. mColShapes.push_back( desc );
  243. return true;
  244. }