pxCloth.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923
  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/pxCloth.h"
  24. #include "console/consoleTypes.h"
  25. #include "scene/sceneManager.h"
  26. #include "scene/sceneRenderState.h"
  27. #include "renderInstance/renderPassManager.h"
  28. #include "lighting/lightQuery.h"
  29. #include "T3D/physics/physicsPlugin.h"
  30. #include "T3D/physics/physx/pxWorld.h"
  31. #include "T3D/physics/physx/pxStream.h"
  32. #include "T3D/physics/physx/pxCasts.h"
  33. #include "gfx/gfxDrawUtil.h"
  34. #include "math/mathIO.h"
  35. #include "core/stream/bitStream.h"
  36. #include "materials/materialManager.h"
  37. #include "materials/baseMatInstance.h"
  38. IMPLEMENT_CO_NETOBJECT_V1( PxCloth );
  39. ConsoleDocClass( PxCloth,
  40. "@brief Rectangular patch of cloth simulated by PhysX.\n\n"
  41. "PxCloth is affected by other objects in the simulation but does not itself "
  42. "affect others, it is essentially a visual effect. Eg, shooting at cloth will "
  43. "disturb it but will not explode the projectile.\n\n"
  44. "Be careful with the cloth size and resolution because it can easily become "
  45. "performance intensive to simulate. A single piece of cloth that is very "
  46. "large or high resolution is also much more expensive than multiple pieces "
  47. "that add up to the same number of verts.\n\n"
  48. "Note that most field docs have been copied from their PhysX counterpart.\n\n"
  49. "@ingroup Physics"
  50. );
  51. enum PxClothAttachment {};
  52. DefineBitfieldType( PxClothAttachment );
  53. ImplementBitfieldType( PxClothAttachment,
  54. "Soon to be deprecated\n"
  55. "@internal" )
  56. { 0, "Bottom Right" },
  57. { 1, "Bottom Left" },
  58. { 2, "Top Right" },
  59. { 3, "Top Left" },
  60. { 4, "Top Center" },
  61. { 5, "Bottom Center" },
  62. { 6, "Right Center" },
  63. { 7, "Left Center" },
  64. { 8, "Top Edge" },
  65. { 9, "Bottom Edge" },
  66. { 10, "Right Edge" },
  67. { 11, "Left Edge" }
  68. EndImplementBitfieldType;
  69. PxCloth::PxCloth()
  70. : mWorld( NULL ),
  71. mScene( NULL ),
  72. mMatInst( NULL )
  73. {
  74. mVertexRenderBuffer = NULL;
  75. mIndexRenderBuffer = NULL;
  76. mMaxVertices = 0;
  77. mMaxIndices = 0;
  78. mClothMesh = NULL;
  79. mCloth = NULL;
  80. mPatchVerts.set( 8, 8 );
  81. mPatchSize.set( 8.0f, 8.0f );
  82. mNetFlags.set( Ghostable | ScopeAlways );
  83. mTypeMask |= StaticObjectType | StaticShapeObjectType;
  84. mReceiveBuffers.setToDefault();
  85. mBendingEnabled = false;
  86. mDampingEnabled = false;
  87. mTriangleCollisionEnabled = false;
  88. mSelfCollisionEnabled = false;
  89. mDensity = 1.0f;
  90. mThickness = 0.1f;
  91. mFriction = 0.25f;
  92. mBendingStiffness = 0.5f;
  93. mDampingCoefficient = 0.25f;
  94. mAttachmentMask = 0;
  95. }
  96. PxCloth::~PxCloth()
  97. {
  98. }
  99. bool PxCloth::onAdd()
  100. {
  101. if ( !Parent::onAdd() )
  102. return false;
  103. // Cloth is only created on the client.
  104. if ( isClientObject() )
  105. {
  106. mWorld = dynamic_cast<PxWorld*>( PHYSICSMGR->getWorld( "client" ) );
  107. if ( !mWorld || !mWorld->getScene() )
  108. {
  109. Con::errorf( "PxCloth::onAdd() - PhysXWorld not initialized... cloth disabled!" );
  110. return true;
  111. }
  112. mScene = mWorld->getScene();
  113. mResetXfm = getTransform();
  114. _createClothPatch();
  115. PhysicsPlugin::getPhysicsResetSignal().notify( this, &PxCloth::onPhysicsReset, 1053.0f );
  116. }
  117. // On the server we use the static update
  118. // to setup the bounds of the cloth.
  119. if ( isServerObject() )
  120. _updateStaticCloth();
  121. addToScene();
  122. // Also the server object never ticks.
  123. if ( isServerObject() )
  124. setProcessTick( false );
  125. return true;
  126. }
  127. void PxCloth::onRemove()
  128. {
  129. SAFE_DELETE( mMatInst );
  130. if ( isClientObject() )
  131. {
  132. _releaseCloth();
  133. _releaseMesh();
  134. PhysicsPlugin::getPhysicsResetSignal().remove( this, &PxCloth::onPhysicsReset );
  135. }
  136. removeFromScene();
  137. Parent::onRemove();
  138. }
  139. void PxCloth::onPhysicsReset( PhysicsResetEvent reset )
  140. {
  141. // Store the reset transform for later use.
  142. if ( reset == PhysicsResetEvent_Store )
  143. mResetXfm = getTransform();
  144. // Recreate the cloth at the last reset position.
  145. _recreateCloth( mResetXfm );
  146. }
  147. void PxCloth::initPersistFields()
  148. {
  149. Parent::initPersistFields();
  150. addField( "material", TypeMaterialName, Offset( mMaterialName, PxCloth ),
  151. "@brief Name of the material to render.\n\n" );
  152. addField( "samples", TypePoint2I, Offset( mPatchVerts, PxCloth ),
  153. "@brief The number of cloth vertices in width and length.\n\n"
  154. "At least two verts should be defined.\n\n");
  155. addField( "size", TypePoint2F, Offset( mPatchSize, PxCloth ),
  156. "@brief The width and height of the cloth.\n\n" );
  157. addField( "bending", TypeBool, Offset( mBendingEnabled, PxCloth ),
  158. "@brief Enables or disables bending resistance.\n\n"
  159. "Set the bending resistance through PxCloth::bendingStiffness." );
  160. addField( "damping", TypeBool, Offset( mDampingEnabled, PxCloth ),
  161. "@brief Enable/disable damping of internal velocities.\n\n" );
  162. addField( "triangleCollision", TypeBool, Offset( mTriangleCollisionEnabled, PxCloth ),
  163. "@brief Not supported in current release (according to PhysX docs).\n\n"
  164. "Enables or disables collision detection of cloth triangles against the scene. "
  165. "If not set, only collisions of cloth particles are detected. If set, "
  166. "collisions of cloth triangles are detected as well." );
  167. addField( "selfCollision", TypeBool, Offset( mSelfCollisionEnabled, PxCloth ),
  168. "@brief Enables or disables self-collision handling within a single piece of cloth.\n\n" );
  169. addField( "density", TypeF32, Offset( mDensity, PxCloth ),
  170. "@brief Density of the cloth (Mass per Area).\n\n" );
  171. addField( "thickness", TypeF32, Offset( mThickness, PxCloth ),
  172. "@brief Value representing how thick the cloth is.\n\n"
  173. "The thickness is usually a fraction of the overall extent of the cloth and "
  174. "should not be set to a value greater than that. A good value is the maximal "
  175. "distance between two adjacent cloth particles in their rest pose. Visual "
  176. "artifacts or collision problems may appear if the thickness is too small.\n\n" );
  177. addField( "friction", TypeF32, Offset( mFriction, PxCloth ),
  178. "@brief Friction coefficient in the range 0 to 1.\n\n"
  179. "Defines the damping of the velocities of cloth particles that are in contact." );
  180. addField( "bendingStiffness", TypeF32, Offset( mBendingStiffness, PxCloth ),
  181. "@brief Bending stiffness of the cloth in the range 0 to 1.\n\n" );
  182. addField( "dampingCoefficient", TypeF32, Offset( mDampingCoefficient, PxCloth ),
  183. "@brief Spring damping of the cloth in the range 0 to 1.\n\n" );
  184. addField( "attachments", TYPEID< PxClothAttachment >(), Offset( mAttachmentMask, PxCloth ),
  185. "@brief Optional way to specify cloth verts that will be attached to the world position "
  186. "it is created at.\n\n" );
  187. // Cloth doesn't support scale.
  188. removeField( "scale" );
  189. }
  190. void PxCloth::inspectPostApply()
  191. {
  192. Parent::inspectPostApply();
  193. // Must have at least 2 verts.
  194. mPatchVerts.x = getMax( 2, mPatchVerts.x );
  195. mPatchVerts.y = getMax( 2, mPatchVerts.y );
  196. if ( isServerObject() )
  197. _updateStaticCloth();
  198. setMaskBits( TransformMask | MaterialMask | ClothMask );
  199. }
  200. U32 PxCloth::packUpdate( NetConnection *conn, U32 mask, BitStream *stream )
  201. {
  202. U32 retMask = Parent::packUpdate( conn, mask, stream );
  203. if ( stream->writeFlag( mask & TransformMask ) )
  204. mathWrite( *stream, getTransform() );
  205. if ( stream->writeFlag( mask & MaterialMask ) )
  206. stream->write( mMaterialName );
  207. if ( stream->writeFlag( mask & ClothMask ) )
  208. {
  209. mathWrite( *stream, mPatchVerts );
  210. mathWrite( *stream, mPatchSize );
  211. stream->write( mAttachmentMask );
  212. stream->writeFlag( mBendingEnabled );
  213. stream->writeFlag( mDampingEnabled );
  214. stream->writeFlag( mTriangleCollisionEnabled );
  215. stream->writeFlag( mSelfCollisionEnabled );
  216. stream->write( mThickness );
  217. stream->write( mFriction );
  218. stream->write( mBendingStiffness );
  219. stream->write( mDampingCoefficient );
  220. stream->write( mDensity );
  221. }
  222. return retMask;
  223. }
  224. void PxCloth::unpackUpdate( NetConnection *conn, BitStream *stream )
  225. {
  226. Parent::unpackUpdate( conn, stream );
  227. // TransformMask
  228. if ( stream->readFlag() )
  229. {
  230. MatrixF mat;
  231. mathRead( *stream, &mat );
  232. setTransform( mat );
  233. }
  234. // MaterialMask
  235. if ( stream->readFlag() )
  236. {
  237. stream->read( &mMaterialName );
  238. SAFE_DELETE( mMatInst );
  239. }
  240. // ClothMask
  241. if ( stream->readFlag() )
  242. {
  243. Point2I patchVerts;
  244. Point2F patchSize;
  245. mathRead( *stream, &patchVerts );
  246. mathRead( *stream, &patchSize );
  247. if ( patchVerts != mPatchVerts ||
  248. !patchSize.equal( mPatchSize ) )
  249. {
  250. mPatchVerts = patchVerts;
  251. mPatchSize = patchSize;
  252. _releaseMesh();
  253. }
  254. U32 attachMask;
  255. stream->read( &attachMask );
  256. if ( attachMask != mAttachmentMask )
  257. {
  258. mAttachmentMask = attachMask;
  259. _releaseCloth();
  260. }
  261. mBendingEnabled = stream->readFlag();
  262. mDampingEnabled = stream->readFlag();
  263. mTriangleCollisionEnabled = stream->readFlag();
  264. mSelfCollisionEnabled = stream->readFlag();
  265. stream->read( &mThickness );
  266. stream->read( &mFriction );
  267. stream->read( &mBendingStiffness );
  268. stream->read( &mDampingCoefficient );
  269. F32 density;
  270. stream->read( &density );
  271. if ( density != mDensity )
  272. {
  273. mDensity = density;
  274. _releaseCloth();
  275. }
  276. if ( isClientObject() &&
  277. isProperlyAdded() &&
  278. mWorld &&
  279. !mCloth )
  280. {
  281. _createClothPatch();
  282. }
  283. _updateClothProperties();
  284. }
  285. }
  286. void PxCloth::_recreateCloth( const MatrixF &transform )
  287. {
  288. if ( !mWorld )
  289. return;
  290. mWorld->getPhysicsResults();
  291. Parent::setTransform( transform );
  292. _createClothPatch();
  293. }
  294. void PxCloth::setTransform( const MatrixF &mat )
  295. {
  296. Parent::setTransform( mat );
  297. setMaskBits( TransformMask );
  298. // Only need to do this if we're on the server
  299. // or if we're not currently ticking physics.
  300. if ( !mWorld || !mWorld->isEnabled() )
  301. _updateStaticCloth();
  302. }
  303. void PxCloth::setScale( const VectorF &scale )
  304. {
  305. // Cloth doesn't support scale as it has plenty
  306. // of complications... sharing meshes, thickness,
  307. // transform origin, etc.
  308. return;
  309. }
  310. void PxCloth::prepRenderImage( SceneRenderState *state )
  311. {
  312. if ( mIsVBDirty )
  313. _updateVBIB();
  314. // Recreate the material if we need to.
  315. if ( !mMatInst )
  316. _initMaterial();
  317. // If we don't have a material instance after the override then
  318. // we can skip rendering all together.
  319. BaseMatInstance *matInst = state->getOverrideMaterial( mMatInst );
  320. if ( !matInst )
  321. return;
  322. MeshRenderInst *ri = state->getRenderPass()->allocInst<MeshRenderInst>();
  323. // If we need lights then set them up.
  324. if ( matInst->isForwardLit() )
  325. {
  326. LightQuery query;
  327. query.init( getWorldSphere() );
  328. query.getLights( ri->lights, 8 );
  329. }
  330. ri->projection = state->getRenderPass()->allocSharedXform(RenderPassManager::Projection);
  331. ri->objectToWorld = &MatrixF::Identity;
  332. ri->worldToCamera = state->getRenderPass()->allocSharedXform(RenderPassManager::View);
  333. ri->type = RenderPassManager::RIT_Mesh;
  334. ri->primBuff = &mPrimBuffer;
  335. ri->vertBuff = &mVB;
  336. ri->matInst = matInst;
  337. ri->prim = state->getRenderPass()->allocPrim();
  338. ri->prim->type = GFXTriangleList;
  339. ri->prim->minIndex = 0;
  340. ri->prim->startIndex = 0;
  341. ri->prim->numPrimitives = mNumIndices / 3;
  342. ri->prim->startVertex = 0;
  343. ri->prim->numVertices = mNumVertices;
  344. ri->defaultKey = matInst->getStateHint();
  345. ri->defaultKey2 = (U32)ri->vertBuff;
  346. state->getRenderPass()->addInst( ri );
  347. }
  348. void PxCloth::_releaseMesh()
  349. {
  350. if ( !mClothMesh )
  351. return;
  352. _releaseCloth();
  353. mWorld->releaseClothMesh( *mClothMesh );
  354. mClothMesh = NULL;
  355. delete [] mVertexRenderBuffer;
  356. mVertexRenderBuffer = NULL;
  357. delete [] mIndexRenderBuffer;
  358. mIndexRenderBuffer = NULL;
  359. }
  360. void PxCloth::_releaseCloth()
  361. {
  362. if ( !mCloth )
  363. return;
  364. mWorld->releaseCloth( *mCloth );
  365. mCloth = NULL;
  366. }
  367. void PxCloth::_initClothMesh()
  368. {
  369. // Make sure we can change the world.
  370. mWorld->releaseWriteLock();
  371. _releaseMesh();
  372. // Must have at least 2 verts.
  373. mPatchVerts.x = getMax( 2, mPatchVerts.x );
  374. mPatchVerts.y = getMax( 2, mPatchVerts.y );
  375. // Generate a uniform cloth patch,
  376. // w and h are the width and height,
  377. // d is the distance between vertices.
  378. mNumVertices = mPatchVerts.x * mPatchVerts.y;
  379. mNumIndices = (mPatchVerts.x-1) * (mPatchVerts.y-1) * 2;
  380. NxClothMeshDesc desc;
  381. desc.numVertices = mNumVertices;
  382. desc.numTriangles = mNumIndices;
  383. desc.pointStrideBytes = sizeof(NxVec3);
  384. desc.triangleStrideBytes = 3*sizeof(NxU32);
  385. desc.points = (NxVec3*)dMalloc(sizeof(NxVec3)*desc.numVertices);
  386. desc.triangles = (NxU32*)dMalloc(sizeof(NxU32)*desc.numTriangles*3);
  387. desc.flags = 0;
  388. U32 i,j;
  389. NxVec3 *p = (NxVec3*)desc.points;
  390. F32 patchWidth = mPatchSize.x / (F32)( mPatchVerts.x - 1 );
  391. F32 patchHeight = mPatchSize.y / (F32)( mPatchVerts.y - 1 );
  392. for (i = 0; i < mPatchVerts.y; i++)
  393. {
  394. for (j = 0; j < mPatchVerts.x; j++)
  395. {
  396. p->set( patchWidth * j, 0.0f, patchHeight * i );
  397. p++;
  398. }
  399. }
  400. NxU32 *id = (NxU32*)desc.triangles;
  401. for (i = 0; i < mPatchVerts.y-1; i++)
  402. {
  403. for (j = 0; j < mPatchVerts.x-1; j++)
  404. {
  405. NxU32 i0 = i * mPatchVerts.x + j;
  406. NxU32 i1 = i0 + 1;
  407. NxU32 i2 = i0 + mPatchVerts.x;
  408. NxU32 i3 = i2 + 1;
  409. if ( (j+i) % 2 )
  410. {
  411. *id++ = i0;
  412. *id++ = i2;
  413. *id++ = i1;
  414. *id++ = i1;
  415. *id++ = i2;
  416. *id++ = i3;
  417. }
  418. else
  419. {
  420. *id++ = i0;
  421. *id++ = i2;
  422. *id++ = i3;
  423. *id++ = i0;
  424. *id++ = i3;
  425. *id++ = i1;
  426. }
  427. }
  428. }
  429. NxCookingInterface *cooker = PxWorld::getCooking();
  430. cooker->NxInitCooking();
  431. // Ok... cook the mesh!
  432. NxCookingParams params;
  433. params.targetPlatform = PLATFORM_PC;
  434. params.skinWidth = 0.01f;
  435. params.hintCollisionSpeed = false;
  436. cooker->NxSetCookingParams( params );
  437. PxMemStream cooked;
  438. if ( cooker->NxCookClothMesh( desc, cooked ) )
  439. {
  440. cooked.resetPosition();
  441. mClothMesh = gPhysicsSDK->createClothMesh( cooked );
  442. }
  443. cooker->NxCloseCooking();
  444. NxVec3 *ppoints = (NxVec3*)desc.points;
  445. NxU32 *triangs = (NxU32*)desc.triangles;
  446. dFree( ppoints );
  447. dFree( triangs );
  448. if ( mClothMesh )
  449. _initReceiveBuffers();
  450. }
  451. void PxCloth::_initReceiveBuffers()
  452. {
  453. // here we setup the buffers through which the SDK returns the dynamic cloth data
  454. // we reserve more memory for vertices than the initial mesh takes
  455. // because tearing creates new vertices
  456. // the SDK only tears cloth as long as there is room in these buffers
  457. mMaxVertices = 3 * mNumVertices;
  458. mMaxIndices = 3 * mNumIndices;
  459. // Allocate Render Buffer for Vertices if it hasn't been done before
  460. mVertexRenderBuffer = new GFXVertexPNTT[mMaxVertices];
  461. mIndexRenderBuffer = new U16[mMaxIndices];
  462. mReceiveBuffers.verticesPosBegin = &(mVertexRenderBuffer[0].point);
  463. mReceiveBuffers.verticesNormalBegin = &(mVertexRenderBuffer[0].normal);
  464. mReceiveBuffers.verticesPosByteStride = sizeof(GFXVertexPNTT);
  465. mReceiveBuffers.verticesNormalByteStride = sizeof(GFXVertexPNTT);
  466. mReceiveBuffers.maxVertices = mMaxVertices;
  467. mReceiveBuffers.numVerticesPtr = &mNumVertices;
  468. // the number of triangles is constant, even if the cloth is torn
  469. mReceiveBuffers.indicesBegin = &mIndexRenderBuffer[0];
  470. mReceiveBuffers.indicesByteStride = sizeof(NxU16);
  471. mReceiveBuffers.maxIndices = mMaxIndices;
  472. mReceiveBuffers.numIndicesPtr = &mNumIndices;
  473. // Set up texture coords.
  474. F32 dx = 1.0f / (F32)(mPatchVerts.x-1);
  475. F32 dy = 1.0f / (F32)(mPatchVerts.y-1);
  476. F32 *coord = (F32*)&mVertexRenderBuffer[0].texCoord;
  477. for ( U32 i = 0; i < mPatchVerts.y; i++)
  478. {
  479. for ( U32 j = 0; j < mPatchVerts.x; j++)
  480. {
  481. coord[0] = j*dx;
  482. coord[1] = i*-dy;
  483. coord += sizeof( GFXVertexPNTT ) / sizeof( F32 );
  484. }
  485. }
  486. // the parent index information would be needed if we used textured cloth
  487. //mReceiveBuffers.parentIndicesBegin = (U32*)malloc(sizeof(U32)*mMaxVertices);
  488. //mReceiveBuffers.parentIndicesByteStride = sizeof(U32);
  489. //mReceiveBuffers.maxParentIndices = mMaxVertices;
  490. //mReceiveBuffers.numParentIndicesPtr = &mNumParentIndices;
  491. mMeshDirtyFlags = 0;
  492. mReceiveBuffers.dirtyBufferFlagsPtr = &mMeshDirtyFlags;
  493. // init the buffers in case we want to draw the mesh
  494. // before the SDK as filled in the correct values
  495. mReceiveBuffers.flags |= NX_MDF_16_BIT_INDICES;
  496. }
  497. bool PxCloth::_createClothPatch()
  498. {
  499. // Make sure we have a mesh.
  500. if ( !mClothMesh )
  501. {
  502. _initClothMesh();
  503. if ( !mClothMesh )
  504. return false;
  505. }
  506. // Make sure we can change the world.
  507. mWorld->releaseWriteLock();
  508. _releaseCloth();
  509. NxClothDesc desc;
  510. desc.globalPose.setRowMajor44( getTransform() );
  511. desc.thickness = mThickness;
  512. desc.density = mDensity;
  513. desc.bendingStiffness = mBendingStiffness;
  514. desc.dampingCoefficient = mDampingCoefficient;
  515. desc.friction = mFriction;
  516. if ( mBendingEnabled )
  517. desc.flags |= NX_CLF_BENDING;
  518. if ( mDampingEnabled )
  519. desc.flags |= NX_CLF_DAMPING;
  520. if ( mTriangleCollisionEnabled )
  521. desc.flags |= NX_CLF_TRIANGLE_COLLISION;
  522. if ( mSelfCollisionEnabled )
  523. desc.flags |= NX_CLF_SELFCOLLISION;
  524. desc.clothMesh = mClothMesh;
  525. desc.meshData = mReceiveBuffers;
  526. if ( !desc.isValid() )
  527. return false;
  528. mCloth = mScene->createCloth( desc );
  529. mIsVBDirty = true;
  530. _updateStaticCloth();
  531. _setupAttachments();
  532. return true;
  533. }
  534. void PxCloth::_updateClothProperties()
  535. {
  536. if ( !mCloth )
  537. return;
  538. mCloth->setThickness( mThickness );
  539. mCloth->setBendingStiffness( mBendingStiffness );
  540. mCloth->setDampingCoefficient( mDampingCoefficient );
  541. mCloth->setFriction( mFriction );
  542. NxU32 flags = NX_CLF_GRAVITY; // TODO: Expose this?
  543. if ( mBendingEnabled )
  544. flags |= NX_CLF_BENDING;
  545. if ( mDampingEnabled )
  546. flags |= NX_CLF_DAMPING;
  547. if ( mTriangleCollisionEnabled )
  548. flags |= NX_CLF_TRIANGLE_COLLISION;
  549. if ( mSelfCollisionEnabled )
  550. flags |= NX_CLF_SELFCOLLISION;
  551. mCloth->setFlags( flags );
  552. }
  553. void PxCloth::_initMaterial()
  554. {
  555. SAFE_DELETE( mMatInst );
  556. Material *material = NULL;
  557. if (mMaterialName.isNotEmpty() )
  558. Sim::findObject( mMaterialName, material );
  559. if ( material )
  560. mMatInst = material->createMatInstance();
  561. else
  562. mMatInst = MATMGR->createMatInstance( "WarningMaterial" );
  563. GFXStateBlockDesc desc;
  564. desc.setCullMode( GFXCullNone );
  565. mMatInst->addStateBlockDesc( desc );
  566. mMatInst->init( MATMGR->getDefaultFeatures(), getGFXVertexFormat<GFXVertexPNTT>() );
  567. }
  568. void PxCloth::_updateVBIB()
  569. {
  570. PROFILE_SCOPE( PxCloth_UpdateVBIB );
  571. mIsVBDirty = false;
  572. // Don't set the VB if the vertex count is the same!
  573. if ( mVB.isNull() || mVB->mNumVerts < mNumVertices )
  574. mVB.set( GFX, mNumVertices, GFXBufferTypeDynamic );
  575. GFXVertexPNTT *vert = mVertexRenderBuffer;
  576. GFXVertexPNTT *secondVert = NULL;
  577. for ( U32 i = 0; i < mNumVertices; i++ )
  578. {
  579. if ( i % (U32)mPatchSize.x == 0 && i != 0 )
  580. {
  581. secondVert = vert;
  582. secondVert--;
  583. vert->tangent = -(vert->point - secondVert->point);
  584. }
  585. else
  586. {
  587. secondVert = vert;
  588. secondVert++;
  589. vert->tangent = vert->point - secondVert->point;
  590. }
  591. vert->tangent.normalize();
  592. vert++;
  593. }
  594. GFXVertexPNTT *vpPtr = mVB.lock();
  595. dMemcpy( vpPtr, mVertexRenderBuffer, sizeof( GFXVertexPNTT ) * mNumVertices );
  596. mVB.unlock();
  597. if ( mPrimBuffer.isNull() || mPrimBuffer->mIndexCount < mNumIndices )
  598. mPrimBuffer.set( GFX, mNumIndices, 0, GFXBufferTypeDynamic );
  599. U16 *pbPtr;
  600. mPrimBuffer.lock( &pbPtr );
  601. dMemcpy( pbPtr, mIndexRenderBuffer, sizeof( U16 ) * mNumIndices );
  602. mPrimBuffer.unlock();
  603. }
  604. void PxCloth::_updateStaticCloth()
  605. {
  606. // Setup the unsimulated world bounds.
  607. mObjBox.set( 0, mThickness * -0.5f, 0,
  608. mPatchSize.x, mThickness * 0.5f, mPatchSize.y );
  609. resetWorldBox();
  610. // If we don't have render buffers then we're done.
  611. if ( !mVertexRenderBuffer || !mIndexRenderBuffer )
  612. return;
  613. // Make sure the VBs are updated.
  614. mIsVBDirty = true;
  615. F32 patchWidth = mPatchSize.x / (F32)(mPatchVerts.x-1);
  616. F32 patchHeight = mPatchSize.y / (F32)(mPatchVerts.y-1);
  617. Point3F normal( 0, 1, 0 );
  618. getTransform().mulV( normal );
  619. GFXVertexPNTT *vert = mVertexRenderBuffer;
  620. for (U32 y = 0; y < mPatchVerts.y; y++)
  621. {
  622. for (U32 x = 0; x < mPatchVerts.x; x++)
  623. {
  624. vert->point.set( patchWidth * x, 0.0f, patchHeight * y );
  625. getTransform().mulP( vert->point );
  626. vert->normal = normal;
  627. vert++;
  628. }
  629. }
  630. U16 *index = mIndexRenderBuffer;
  631. mNumIndices = (mPatchVerts.x-1) * (mPatchVerts.y-1) * 6;
  632. U16 yOffset = mPatchVerts.x;
  633. for (U32 y = 0; y < mPatchVerts.y-1; y++)
  634. {
  635. for (U32 x = 0; x < mPatchVerts.x-1; x++)
  636. {
  637. U16 base = x + ( yOffset * y );
  638. index[0] = base;
  639. index[1] = base + 1;
  640. index[2] = base + 1 + yOffset;
  641. index[3] = base + 1 + yOffset;
  642. index[4] = base + yOffset;
  643. index[5] = base;
  644. index += 6;
  645. }
  646. }
  647. }
  648. void PxCloth::processTick( const Move *move )
  649. {
  650. // Make sure the cloth is created.
  651. if ( !mCloth )
  652. return;
  653. // TODO: Remove this hack!
  654. const bool enableWind = Con::getBoolVariable( "$PxCloth::enableWind", false );
  655. if ( enableWind )
  656. {
  657. NxVec3 windVec( 25.0f + NxMath::rand(-5.0f, 5.0f),
  658. NxMath::rand(-5.0f, 5.0f),
  659. NxMath::rand(-5.0f, 5.0f) );
  660. mCloth->setWindAcceleration( windVec );
  661. // Wake the cloth!
  662. mCloth->wakeUp();
  663. }
  664. else
  665. mCloth->setWindAcceleration( NxVec3( 0, 0, 0 ) );
  666. // Update bounds.
  667. if ( mWorld->getEnabled() )
  668. {
  669. NxBounds3 box;
  670. mCloth->getWorldBounds( box );
  671. Point3F min = pxCast<Point3F>( box.min );
  672. Point3F max = pxCast<Point3F>( box.max );
  673. mWorldBox.set( min, max );
  674. mObjBox = mWorldBox;
  675. getWorldTransform().mul( mObjBox );
  676. }
  677. else
  678. {
  679. mObjBox.set( 0, mThickness * -0.5f, 0,
  680. mPatchSize.x, mThickness * 0.5f, mPatchSize.y );
  681. }
  682. resetWorldBox();
  683. // Update the VB on the next render.
  684. mIsVBDirty = true;
  685. }
  686. void PxCloth::interpolateTick( F32 delta )
  687. {
  688. // Nothing to do for now!
  689. }
  690. bool PxCloth::onNewDataBlock( GameBaseData *dptr, bool reload )
  691. {
  692. return false;
  693. }
  694. void PxCloth::_setupAttachments()
  695. {
  696. if ( !mCloth || !mWorld )
  697. return;
  698. // Set up attachments
  699. // Bottom right = bit 0
  700. // Bottom left = bit 1
  701. // Top right = bit 2
  702. // Top left = bit 3
  703. if ( mAttachmentMask & BIT( 0 ) )
  704. mCloth->attachVertexToGlobalPosition( 0, mCloth->getPosition( 0 ) );
  705. if ( mAttachmentMask & BIT( 1 ) )
  706. mCloth->attachVertexToGlobalPosition( mPatchVerts.x-1, mCloth->getPosition( mPatchVerts.x-1 ) );
  707. if ( mAttachmentMask & BIT( 2 ) )
  708. mCloth->attachVertexToGlobalPosition( mPatchVerts.x * mPatchVerts.y - mPatchVerts.x, mCloth->getPosition( mPatchVerts.x * mPatchVerts.y - mPatchVerts.x ) );
  709. if ( mAttachmentMask & BIT( 3 ) )
  710. mCloth->attachVertexToGlobalPosition( mPatchVerts.x * mPatchVerts.y - 1, mCloth->getPosition( mPatchVerts.x * mPatchVerts.y - 1 ) );
  711. if ( mAttachmentMask & BIT( 4 ) )
  712. mCloth->attachVertexToGlobalPosition( mPatchVerts.x * mPatchVerts.y - (mPatchVerts.x/2), mCloth->getPosition( mPatchVerts.x * mPatchVerts.y - (mPatchVerts.x/2) ) );
  713. if ( mAttachmentMask & BIT( 5 ) )
  714. mCloth->attachVertexToGlobalPosition( (mPatchVerts.x/2), mCloth->getPosition( (mPatchVerts.x/2) ) );
  715. if ( mAttachmentMask & BIT( 6 ) )
  716. mCloth->attachVertexToGlobalPosition( mPatchVerts.x * (mPatchVerts.y/2), mCloth->getPosition( mPatchVerts.x * (mPatchVerts.y/2) ) );
  717. if ( mAttachmentMask & BIT( 7 ) )
  718. mCloth->attachVertexToGlobalPosition( mPatchVerts.x * (mPatchVerts.y/2) + (mPatchVerts.x-1), mCloth->getPosition( mPatchVerts.x * (mPatchVerts.y/2) + (mPatchVerts.x-1) ) );
  719. if ( mAttachmentMask & BIT( 8 ) )
  720. for ( U32 i = mPatchVerts.x * mPatchVerts.y - mPatchVerts.x; i < mPatchVerts.x * mPatchVerts.y; i++ )
  721. mCloth->attachVertexToGlobalPosition( i, mCloth->getPosition( i ) );
  722. if ( mAttachmentMask & BIT( 9 ) )
  723. for ( U32 i = 0; i < mPatchVerts.x; i++ )
  724. mCloth->attachVertexToGlobalPosition( i, mCloth->getPosition( i ) );
  725. if ( mAttachmentMask & BIT( 10 ) )
  726. for ( U32 i = 0; i < mPatchVerts.x * mPatchVerts.y; i+=mPatchVerts.x )
  727. mCloth->attachVertexToGlobalPosition( i, mCloth->getPosition( i ) );
  728. if ( mAttachmentMask & BIT( 11 ) )
  729. for ( U32 i = mPatchVerts.x-1; i < mPatchVerts.x * mPatchVerts.y; i+=mPatchVerts.x )
  730. mCloth->attachVertexToGlobalPosition( i, mCloth->getPosition( i ) );
  731. }