PhysCloth.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. #include "PhysCloth.h"
  2. #include "PhysicsScene.h"
  3. PhysCloth::PhysCloth( const char * filename, long fileline,
  4. IPhysicsScene& physScene,
  5. IClothRenderInfo& render,
  6. IClothMeshBuilder& builder,
  7. SimulationData& externalSimData,
  8. float density) :
  9. IPhysCloth(&physScene),
  10. m_physCloth(NULL),
  11. m_isSleeping(false),
  12. m_builder(builder)
  13. {
  14. SetFileLine(filename, fileline);
  15. m_internalSimData.maxVertices = externalSimData.maxVertexCount;
  16. m_internalSimData.maxIndices = externalSimData.maxIndexCount;
  17. m_internalSimData.maxParentIndices = 0;
  18. if (externalSimData.parentIB)
  19. m_internalSimData.maxParentIndices = m_internalSimData.maxVertices;
  20. m_internalSimData.verticesPosBegin = externalSimData.posBuffer;
  21. m_internalSimData.verticesNormalBegin = NULL;
  22. if (render.NeedNormals()) // указываем на нормали, если надо
  23. m_internalSimData.verticesNormalBegin = ((char*)m_internalSimData.verticesPosBegin) + render.GetNormalOffset();
  24. m_internalSimData.indicesBegin = externalSimData.ib;
  25. m_internalSimData.parentIndicesBegin = externalSimData.parentIB;
  26. m_internalSimData.indicesByteStride = externalSimData.indexStride;
  27. m_internalSimData.verticesPosByteStride = externalSimData.posStride;
  28. m_internalSimData.verticesNormalByteStride = externalSimData.posStride;
  29. m_internalSimData.parentIndicesByteStride = 0;
  30. if (externalSimData.parentIB)
  31. m_internalSimData.parentIndicesByteStride = sizeof(unsigned int);
  32. m_internalSimData.numIndicesPtr = &externalSimData.indexCount;
  33. m_internalSimData.numVerticesPtr = &externalSimData.vertexCount;
  34. m_internalSimData.numParentIndicesPtr = &externalSimData.parentIndexCount;
  35. m_internalSimData.dirtyBufferFlagsPtr = &externalSimData.dirtyFlags;
  36. m_internalSimData.flags = externalSimData.indexStride==2 ? NX_MDF_16_BIT_INDICES : 0;
  37. NxClothDesc clothDesc;
  38. clothDesc.clothMesh = &(m_builder.GetMesh());
  39. clothDesc.meshData = m_internalSimData;
  40. clothDesc.stretchingStiffness = 1.0f;
  41. clothDesc.bendingStiffness = 1.0f;
  42. clothDesc.dampingCoefficient = 1.0f;
  43. clothDesc.friction = 1.0f;
  44. clothDesc.density = density; // 1.0f - default
  45. clothDesc.thickness = 0.10f; // 0.01f - default
  46. clothDesc.solverIterations = 5; // 5 - default
  47. //clothDesc.flags |= NX_CLF_BENDING | NX_CLF_BENDING_ORTHO;
  48. // clothDesc.flags |= NX_CLF_DAMPING | NX_CLF_COMDAMPING;
  49. if (m_builder.IsTearable())
  50. clothDesc.flags |= NX_CLF_TEARABLE;
  51. if (scene->IsHardware())
  52. clothDesc.flags |= NX_CLF_HARDWARE;
  53. /*clothDesc.collisionGroup = phys_player;
  54. clothDesc.groupsMask.bits0 = 1;
  55. clothDesc.groupsMask.bits1 = 0;
  56. clothDesc.groupsMask.bits2 = 0;
  57. clothDesc.groupsMask.bits3 = 0;*/
  58. // FIX-ME Временно добавил отключение коллижена
  59. clothDesc.flags |= NX_CLF_DISABLE_COLLISION;
  60. m_physCloth = ((PhysicsScene*)scene)->Scene().createCloth(clothDesc);
  61. Assert(m_physCloth);
  62. m_builder.AddRef();
  63. }
  64. PhysCloth::~PhysCloth()
  65. {
  66. if (m_physCloth)
  67. {
  68. ((PhysicsScene*)scene)->Scene().releaseCloth(*m_physCloth);
  69. m_physCloth = NULL;
  70. }
  71. m_builder.Release();
  72. }
  73. // присоединить ткань ко всем объектам которые она пересекает
  74. void PhysCloth::Attach(bool twoWayInteraction, bool tearable)
  75. {
  76. unsigned int flags = 0;
  77. if (twoWayInteraction)
  78. flags |= NX_CLOTH_ATTACHMENT_TWOWAY;
  79. if (tearable)
  80. flags |= NX_CLOTH_ATTACHMENT_TEARABLE;
  81. m_physCloth->attachToCollidingShapes(flags);
  82. }
  83. // присоединить ткань ближайшим вертексом к мировой точке
  84. unsigned int PhysCloth::Attach(const Vector& pos)
  85. {
  86. unsigned int vID = 0;
  87. float length = 0.0f;
  88. float min = FLT_MAX;
  89. array<NxVec3> vPosBuf(__FILE__, __LINE__);
  90. vPosBuf.AddElements(m_physCloth->getNumberOfParticles());
  91. m_physCloth->getPositions(&vPosBuf[0]);
  92. for (dword i = 0; i < vPosBuf.Size(); ++i)
  93. if ( (length=(Nx(vPosBuf[i])-pos).GetLength()) < min )
  94. {
  95. vID = i;
  96. min = length;
  97. }
  98. Attach(vID, pos);
  99. return vID;
  100. }
  101. // присоединить ткань заданным вертексом к мировой точке
  102. void PhysCloth::Attach(unsigned int vertexID, const Vector& pos)
  103. {
  104. Assert(vertexID < m_physCloth->getNumberOfParticles());
  105. m_physCloth->attachVertexToGlobalPosition(vertexID, Nx(pos));
  106. }
  107. // присоединить ткань к физ. телу
  108. void PhysCloth::Attach(IPhysRigidBody& body, bool twoWayInteraction, bool tearable)
  109. {
  110. unsigned int flags = 0;
  111. if (twoWayInteraction)
  112. flags |= NX_CLOTH_ATTACHMENT_TWOWAY;
  113. if (tearable)
  114. flags |= NX_CLOTH_ATTACHMENT_TEARABLE;
  115. PhysInternal nxActor;
  116. body.GetInternals(nxActor);
  117. dword shapesCount = nxActor.actor->getNbShapes();
  118. for (dword i = 0; i < shapesCount; ++i)
  119. m_physCloth->attachToShape(nxActor.actor->getShapes()[i], flags);
  120. }
  121. // присоединить ткань к заданным элементам физ. тела
  122. void PhysCloth::Attach(IPhysRigidBody& body, const array<unsigned int>& shapes, bool twoWayInteraction, bool tearable)
  123. {
  124. unsigned int flags = 0;
  125. if (twoWayInteraction)
  126. flags |= NX_CLOTH_ATTACHMENT_TWOWAY;
  127. if (tearable)
  128. flags |= NX_CLOTH_ATTACHMENT_TEARABLE;
  129. PhysInternal nxActor;
  130. body.GetInternals(nxActor);
  131. dword shapesCount = shapes.Size();
  132. for (dword i = 0; i < shapesCount; ++i)
  133. m_physCloth->attachToShape(nxActor.actor->getShapes()[shapes[i]], flags);
  134. }
  135. // присоединить ткань к заданным элементам физ. тела
  136. void PhysCloth::Attach(IPhysRigidBody& body, int shapeIndex, const Vector & vPos, int vertexID, bool twoWayInteraction, bool tearable)
  137. {
  138. unsigned int flags = 0;
  139. if (twoWayInteraction)
  140. flags |= NX_CLOTH_ATTACHMENT_TWOWAY;
  141. if (tearable)
  142. flags |= NX_CLOTH_ATTACHMENT_TEARABLE;
  143. PhysInternal phiActor;
  144. body.GetInternals( phiActor );
  145. NxShape * pShape = phiActor.actor->getShapes()[shapeIndex];
  146. m_physCloth->attachVertexToShape(vertexID, pShape, *(NxVec3*)&vPos, flags);
  147. }
  148. // отсоединить все закрепленные точки ткани
  149. void PhysCloth::Detach()
  150. {
  151. dword vertCount = m_physCloth->getNumberOfParticles();
  152. for (dword i = 0; i < vertCount; ++i)
  153. m_physCloth->freeVertex(i);
  154. }
  155. // отсоединить закрепленную точку ткани
  156. void PhysCloth::Detach(unsigned int vertexID)
  157. {
  158. Assert(vertexID < m_physCloth->getNumberOfParticles());
  159. m_physCloth->freeVertex(vertexID);
  160. }
  161. // отсоединить все точки закрепленные на физическом теле
  162. void PhysCloth::Detach(IPhysRigidBody& body)
  163. {
  164. PhysInternal nxActor;
  165. body.GetInternals(nxActor);
  166. dword shapesCount = nxActor.actor->getNbShapes();
  167. for (dword i = 0; i < shapesCount; ++i)
  168. m_physCloth->detachFromShape(nxActor.actor->getShapes()[i]);
  169. }
  170. // отсоединить все точки закрепленные на элементах физ. тела
  171. void PhysCloth::Detach(IPhysRigidBody& body, const array<unsigned int>& shapes)
  172. {
  173. PhysInternal nxActor;
  174. body.GetInternals(nxActor);
  175. dword shapesCount = shapes.Size();
  176. for (dword i = 0; i < shapesCount; ++i)
  177. m_physCloth->detachFromShape(nxActor.actor->getShapes()[shapes[i]]);
  178. }
  179. // получить ABB ткани
  180. Box PhysCloth::GetABB() const
  181. {
  182. NxVec3 dims;
  183. NxVec3 center;
  184. NxBounds3 bounds;
  185. Box box;
  186. m_physCloth->getWorldBounds(bounds);
  187. bounds.getDimensions(dims);
  188. bounds.getCenter(center);
  189. box.center = Nx(center);
  190. box.size = Nx(dims);
  191. return box;
  192. }
  193. // получить кол-во вершин в ткани
  194. unsigned int PhysCloth::GetVertexCount() const
  195. {
  196. return m_physCloth->getNumberOfParticles();
  197. }
  198. // приложить силу/импульс в точку ткани
  199. void PhysCloth::AddForceAtPos(const Vector & pos, float magnitude, float radius, PhysForceMode forceMode)
  200. {
  201. m_physCloth->addForceAtPos(Nx(pos), magnitude, radius, Nx(forceMode));
  202. }
  203. // разорвать ткань в заданной точке
  204. void PhysCloth::TearVertex(unsigned int vertexID, const Vector & normal)
  205. {
  206. Assert(vertexID < m_physCloth->getNumberOfParticles());
  207. m_physCloth->tearVertex(vertexID, Nx(normal));
  208. }
  209. // разорвать ткань в заданной точке
  210. void PhysCloth::Tear(unsigned int vertexID, bool tearWholeTriangle)
  211. {
  212. Assert(vertexID < m_physCloth->getNumberOfParticles());
  213. m_physCloth->tearVertex(vertexID, NxVec3(1.0f, 1.0f, 0.0f));
  214. if (tearWholeTriangle)
  215. {
  216. m_physCloth->tearVertex(vertexID, NxVec3(-1.0f, 1.0f, 0.0f));
  217. m_physCloth->tearVertex(vertexID, NxVec3(0.0f, 1.0f, 0.0f));
  218. m_physCloth->tearVertex(vertexID, NxVec3(1.0f, 0.0f, 0.0f));
  219. }
  220. }
  221. // проверить пересечение ткани и луча
  222. bool PhysCloth::Raycast(const Vector& from, const Vector& to, Vector * hitPos, unsigned int * vertexID) const
  223. {
  224. NxRay ray;
  225. NxVec3 pos;
  226. unsigned int vID;
  227. ray.orig = Nx(from);
  228. ray.dir = Nx(to-from);
  229. float maxDist = ray.dir.normalize();
  230. bool result = m_physCloth->raycast(ray, pos, vID);
  231. if (!result || (Nx(pos)-from).GetLength() > maxDist)
  232. return false;
  233. if (hitPos)
  234. *hitPos = Nx(pos);
  235. if (vertexID)
  236. *vertexID = vID;
  237. return true;
  238. }
  239. // установить коэффициент разрыва ткани
  240. void PhysCloth::SetTearCoef(float coef)
  241. {
  242. m_physCloth->setTearFactor(coef);
  243. }
  244. // получить коэффициент разрыва ткани
  245. float PhysCloth::GetTearCoef() const
  246. {
  247. return m_physCloth->getTearFactor();
  248. }
  249. // установить коэффициент разрыва в точке крепления ткани
  250. void PhysCloth::SetAttachmentTearCoef(float coef)
  251. {
  252. m_physCloth->setAttachmentTearFactor(coef);
  253. }
  254. // получить коэффициент разрыва в точке крепления ткани
  255. float PhysCloth::GetAttachmentTearCoef() const
  256. {
  257. return m_physCloth->getAttachmentTearFactor();
  258. }
  259. // установить ускорение
  260. void PhysCloth::SetAcceleration(const Vector& accel )
  261. {
  262. m_physCloth->setExternalAcceleration(Nx(accel));
  263. }
  264. // получить ускорение
  265. Vector PhysCloth::GetAcceleration() const
  266. {
  267. return Nx(m_physCloth->getExternalAcceleration());
  268. }
  269. // установить кол-во итераций солвера
  270. void PhysCloth::SetSolverIterations(unsigned int count)
  271. {
  272. m_physCloth->setSolverIterations(count);
  273. }
  274. // сохранить внутреннее состояние и прекратить симуляцию
  275. void PhysCloth::Sleep()
  276. {
  277. if ( m_isSleeping )
  278. return;
  279. m_physCloth->setFlags( m_physCloth->getFlags() | NX_CLF_STATIC );
  280. m_isSleeping = true;
  281. }
  282. // восстановить внутреннее состояние и продолжить симуляцию
  283. void PhysCloth::WakeUp(const Matrix& mtx)
  284. {
  285. if ( !m_isSleeping )
  286. return;
  287. Transform(mtx);
  288. m_physCloth->setFlags( m_physCloth->getFlags() & ~NX_CLF_STATIC );
  289. m_physCloth->wakeUp();
  290. m_isSleeping = false;
  291. }
  292. // применить трансформацию к каждой вершине ткани
  293. void PhysCloth::Transform(const Matrix& mtx)
  294. {
  295. array<NxVec3> vPosBuf(__FILE__, __LINE__);
  296. vPosBuf.AddElements(m_physCloth->getNumberOfParticles());
  297. m_physCloth->getPositions(&vPosBuf[0]);
  298. for (dword i = 0; i < vPosBuf.Size(); ++i)
  299. vPosBuf[i] = Nx(mtx.MulVertex(Nx(vPosBuf[i])));
  300. m_physCloth->setPositions(&vPosBuf[0]);
  301. }
  302. // задать бокс где будет жить ткань, при выходе за этот бокс вершины ткани удаляются
  303. void PhysCloth::SetValidBox(const Vector& min, const Vector& max)
  304. {
  305. NxBounds3 bounds;
  306. bounds.set(Nx(min), Nx(max));
  307. m_physCloth->setValidBounds(bounds);
  308. }
  309. // включить/выключить использование ValidBox'а
  310. void PhysCloth::EnableValidBox(bool enable)
  311. {
  312. if (enable)
  313. m_physCloth->setFlags(m_physCloth->getFlags() | NX_CLF_VALIDBOUNDS);
  314. else
  315. m_physCloth->setFlags(m_physCloth->getFlags() & ~NX_CLF_VALIDBOUNDS);
  316. }