PhysicsScene.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882
  1. #include "PhysicsScene.h"
  2. #include "PhysicsService.h"
  3. #include "..\Common_h\Render.h"
  4. #include "..\Common_h\FileService.h"
  5. #include "PhysCharacter.h"
  6. #include "PhysRigidBody.h"
  7. #include "PhysCloth.h"
  8. #include "PhysTriangleMesh.h"
  9. #include "PhysRagdoll.h"
  10. #include "PhysMaterial.h"
  11. #include "NxCooking.h"
  12. #include "ClothProxy.h"
  13. #include "CombinedProxy.h"
  14. #include "PlaneProxy.h"
  15. #include "BoxProxy.h"
  16. #include "MaterialProxy.h"
  17. #include "SphereProxy.h"
  18. #include "CapsuleProxy.h"
  19. #include "MeshProxy.h"
  20. #include "CharacterProxy.h"
  21. #include "RagdollProxy.h"
  22. #include "ConnectorProxy.h"
  23. #include "time.h"
  24. //============================================================================================
  25. #define CONTACT_FORCE_THRESHOLD 0.5f
  26. PhysicsScene::PhysicsScene(PhysicsService * srv) :
  27. m_objects(_FL_, 32),
  28. m_materials(_FL_),
  29. m_proxies(_FL_, 32),
  30. m_meshes(_FL_, 32),
  31. m_conproxies(_FL_),
  32. m_clothproxies(_FL_),
  33. m_hSimulateDoneEvent(NULL),
  34. m_lastDeltaTime(0.0f),
  35. m_normalizeObjectIndex(0),
  36. m_debugDraw(false),
  37. m_OverlapShapes(_FL_, 4),
  38. m_spheres(_FL_, 1024)
  39. {
  40. m_contactReport.m_scene = this;
  41. m_service = srv;
  42. Assert(m_service);
  43. InitScene();
  44. if (IsMultiThreading())
  45. {
  46. m_hSimulateDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL); Assert(m_hSimulateDoneEvent);
  47. }
  48. m_sceneChangedIndex = 0;
  49. }
  50. PhysicsScene::~PhysicsScene()
  51. {
  52. }
  53. void PhysicsScene::InitScene()
  54. {
  55. //Создаём сцену
  56. NxSceneDesc sceneDesc;
  57. sceneDesc.gravity = NxVec3(0.0f, -9.8f, 0.0f);
  58. //отключаем обработку физики в другом потоке средствами physx'a
  59. sceneDesc.flags &= ~NX_SF_SIMULATE_SEPARATE_THREAD;
  60. m_scene = m_service->physicsSDK->createScene(sceneDesc);
  61. Assert(m_scene);
  62. m_service->scenes.Add(this);
  63. //m_scene->setTiming(1.0f/60.0f, 8, NX_TIMESTEP_FIXED);
  64. //m_scene->setTiming(1.0f/60.0f, 8, NX_TIMESTEP_VARIABLE);
  65. m_currentTime = 0.0f;
  66. NxMaterial * defaultMaterial = m_scene->getMaterialFromIndex(0);
  67. defaultMaterial->setRestitution((NxReal)0.0);
  68. defaultMaterial->setStaticFriction((NxReal)0.5);
  69. defaultMaterial->setDynamicFriction((NxReal)0.5);
  70. PhysicsCollisionGroup groups[] = { phys_world, // 1
  71. phys_player, // 2
  72. phys_character, // 3
  73. phys_ragdoll, // 4
  74. phys_particles, // 5
  75. phys_ship, // 6
  76. phys_grp1, // 7
  77. phys_grp2, // 8
  78. phys_grp3, // 9
  79. phys_grp4, // 10
  80. phys_nocollision, // 11
  81. phys_pair, // 12
  82. phys_playerctrl, // 13
  83. phys_physobjects, // 14
  84. phys_charitems, // 15
  85. phys_bloodpatch, // 16
  86. phys_enemy, // 17
  87. phys_ally, // 18
  88. phys_boss, // 19
  89. phys_grass}; // 20
  90. const unsigned int dim = sizeof(groups)/sizeof(groups[0]);
  91. unsigned char collisions[dim][dim] =
  92. //матрецо коллизий 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
  93. {{ 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0}, // 1
  94. { 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // 2
  95. { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, // 3
  96. { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // 4
  97. { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // 5
  98. { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // 6
  99. { 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // 7
  100. { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // 8
  101. { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // 9
  102. { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // 10
  103. { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // 11
  104. { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, // 12
  105. { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0}, // 13
  106. { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0}, // 14
  107. { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // 15
  108. { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}, // 16
  109. { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0}, // 17
  110. { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}, // 18
  111. { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0}, // 19
  112. { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}}; // 20
  113. for(unsigned int i = 0; i < sizeof(groups)/sizeof(groups[0]); ++i)
  114. for(unsigned int j = 0; j < sizeof(groups)/sizeof(groups[0]); ++j)
  115. {
  116. m_scene->setGroupCollisionFlag(groups[i], groups[j], collisions[j][i] || collisions[i][j]);
  117. }
  118. m_scene->setActorGroupPairFlags(phys_world, phys_physobjects, NX_NOTIFY_FORCES | NX_NOTIFY_ON_START_TOUCH);
  119. m_scene->setActorGroupPairFlags(phys_world, phys_charitems, NX_NOTIFY_FORCES | NX_NOTIFY_ON_START_TOUCH);
  120. m_scene->setActorGroupPairFlags(phys_physobjects, phys_physobjects, NX_NOTIFY_FORCES | NX_NOTIFY_ON_START_TOUCH);
  121. m_scene->setUserContactReport(&m_contactReport);
  122. // рождаем материалы
  123. m_materials.Add(NEW PhysMaterial(_FL_, this, m_scene->getMaterialFromIndex(0)));
  124. for (unsigned int i = mtl_default+1; i < mtl_last; ++i)
  125. CreatePhysMaterial(_FL_);
  126. }
  127. void PhysicsScene::ReleaseScene()
  128. {
  129. for (int i = m_objects.Size()-1; i >= 0; --i)
  130. m_objects[i]->ForceRelease();
  131. m_objects.DelAll();
  132. //for (int i = m_proxies.Size() - 1; i >= 0 ; --i)
  133. // m_proxies[i]->OnSyncRelease();
  134. m_proxies.DelAll();
  135. //for (int i = m_conproxies.Size() - 1; i >= 0 ; --i)
  136. // m_conproxies[i]->OnSyncRelease();
  137. m_conproxies.DelAll();
  138. //for (int i = m_clothproxies.Size() - 1; i >= 0 ; --i)
  139. // m_clothproxies[i]->OnSyncRelease();
  140. m_clothproxies.DelAll();
  141. for (unsigned int i = 0; i < m_materials.Size(); ++i)
  142. delete m_materials[i];
  143. m_materials.DelAll();
  144. m_service->scenes.Del(this);
  145. if(m_scene) m_service->physicsSDK->releaseScene(*m_scene);
  146. m_scene = null;
  147. }
  148. //Удалить сцену
  149. void PhysicsScene::Release()
  150. {
  151. if (IsMultiThreading())
  152. {
  153. CloseHandle(m_hSimulateDoneEvent);
  154. m_hSimulateDoneEvent = null;
  155. }
  156. ReleaseScene();
  157. delete this;
  158. }
  159. //Создать плоскость
  160. IPhysPlane * PhysicsScene::CreatePlane(const char * cppfile, long cppline, const Vector & n, float d)
  161. {
  162. PlaneProxy * p = NEW PlaneProxy(n, d, *this);
  163. p->SetFileLine(cppfile, cppline);
  164. m_objects.Add((IPhysBase *)p);
  165. m_proxies.Add(p);
  166. return p;
  167. }
  168. //Создать ящик
  169. IPhysBox * PhysicsScene::CreateBox(const char * cppfile, long cppline, const Vector & size, const Matrix & transform, bool isDynamic, float density)
  170. {
  171. BoxProxy * p = NEW BoxProxy(size, transform, isDynamic, density, *this);
  172. p->SetFileLine(cppfile, cppline);
  173. m_objects.Add(p);
  174. m_proxies.Add(p);
  175. return p;
  176. }
  177. //Создать шар
  178. IPhysSphere * PhysicsScene::CreateSphere(const char * cppfile, long cppline, float radius, const Matrix & transform, bool isDynamic, float density)
  179. {
  180. SphereProxy * p = NEW SphereProxy(radius, transform, isDynamic, density, *this);
  181. p->SetFileLine(cppfile, cppline);
  182. m_objects.Add(p);
  183. m_proxies.Add(p);
  184. return p;
  185. }
  186. //Создать капсулу
  187. IPhysCapsule * PhysicsScene::CreateCapsule(const char * cppfile, long cppline, float radius, float height, const Matrix & transform, bool isDynamic, float density)
  188. {
  189. CapsuleProxy * p = NEW CapsuleProxy(radius, height, transform, isDynamic, density, *this);
  190. p->SetFileLine(cppfile, cppline);
  191. m_objects.Add(p);
  192. m_proxies.Add(p);
  193. return p;
  194. }
  195. //Создать объект состоящий из множества фигур
  196. IPhysCombined * PhysicsScene::CreateCombined(const char * cppfile, long cppline, const Matrix & transform, bool isDynamic, float density)
  197. {
  198. CombinedProxy * p = NEW CombinedProxy(cppfile, cppline, transform, isDynamic, density, *this);
  199. // setfileline делается внутри combinedproxy
  200. //p->SetFileLine(cppfile, cppline);
  201. m_objects.Add(p);
  202. m_proxies.Add(p);
  203. return p;
  204. }
  205. // Создать ткань
  206. IPhysCloth * PhysicsScene::CreateCloth (const char * cppfile, long cppline, IClothRenderInfo& render, IClothMeshBuilder& builder, IPhysCloth::SimulationData& dataBuffer, float density)
  207. {
  208. ClothProxy * pNewCloth = NEW ClothProxy(*this, render, builder, dataBuffer, density);
  209. pNewCloth->SetFileLine(cppfile, cppline);
  210. m_objects.Add(pNewCloth);
  211. m_clothproxies.Add(pNewCloth);
  212. return pNewCloth;
  213. }
  214. //Создать цельный объект из сетки
  215. IPhysRigidBody * PhysicsScene::CreateMesh(const char * cppfile, long cppline, const MeshInit * meshes, dword numMeshes, bool bDynamic, float density)
  216. {
  217. MeshProxy * p = NEW MeshProxy(meshes, numMeshes, bDynamic, density, *this);
  218. p->SetFileLine(cppfile, cppline);
  219. m_objects.Add(p);
  220. m_proxies.Add(p);
  221. return p;
  222. }
  223. //Соединить 2 цельных объекта
  224. IPhysRigidBodyConnector * PhysicsScene::Connect(IPhysRigidBody * left, IPhysRigidBody * right, float brokeForce)
  225. {
  226. ConnectorProxy * p = NEW ConnectorProxy(*this, left, right, brokeForce);
  227. m_objects.Add(p);
  228. m_conproxies.Add(p);
  229. return p;
  230. }
  231. //Создать физическое представление персонажа (капсулой)
  232. IPhysCharacter * PhysicsScene::CreateCharacter(const char * cppfile, long cppline, float radius, float height)
  233. {
  234. CharacterProxy * p = NEW CharacterProxy(radius, height, *this);
  235. p->SetFileLine(cppfile, cppline);
  236. m_objects.Add(p);
  237. m_proxies.Add(p);
  238. return p;
  239. }
  240. void PhysicsScene::Error(const char * error, const char * cppfile, long cppline)
  241. {
  242. if (error)
  243. api->Trace(error);
  244. api->Trace("file: %s, line: %d", cppfile, cppline);
  245. }
  246. //Создать рэгдол
  247. IPhysRagdoll * PhysicsScene::CreateRagdoll(const char * cppfile, long cppline, const void * data, dword dataSize)
  248. {
  249. if(!data)
  250. {
  251. Error("Physics: Can't create ragdoll, invalidate data pointer (null)", cppfile, cppline);
  252. return null;
  253. }
  254. if(!dataSize)
  255. {
  256. Error("Physics: Can't create ragdoll, invalidate data size (0)", cppfile, cppline);
  257. return null;
  258. }
  259. RagdollProxy * ragdoll = NEW RagdollProxy(data, dataSize, *this);
  260. ragdoll->SetFileLine(cppfile, cppline);
  261. m_objects.Add(ragdoll);
  262. m_proxies.Add(ragdoll);
  263. return ragdoll;
  264. }
  265. //Создать редактируемый рэгдол
  266. IPhysEditableRagdoll * PhysicsScene::CreateEditableRagdoll()
  267. {
  268. RagdollProxy * p = NEW RagdollProxy(*this);
  269. m_objects.Add(p);
  270. m_proxies.Add(p);
  271. return p;
  272. }
  273. IPhysEditableRagdoll * PhysicsScene::CreateRealEditableRagdoll()
  274. {
  275. PhysRagdoll * p = NEW PhysRagdoll(null, _FL_, this);
  276. return p;
  277. }
  278. //Создать физический материал
  279. IPhysMaterial * PhysicsScene::CreatePhysMaterial(const char * cppfile, long cppline, float statFriction, float dynFriction, float restitution)
  280. {
  281. MaterialProxy * mat = NEW MaterialProxy(*this, statFriction, dynFriction, restitution);
  282. mat->SetFileLine(cppfile, cppline);
  283. m_materials.Add(mat);
  284. m_proxies.Add(mat);
  285. return mat;
  286. }
  287. IPhysMaterial * PhysicsScene::GetPhysMaterial(PhysMaterialGroup group) const
  288. {
  289. return m_materials[group];
  290. }
  291. class PhysSceneMeshesReport : public NxUserEntityReport<NxShape*>
  292. {
  293. private:
  294. // ссылка на массив куда добавляются все прошедшие тест меши
  295. array<NxTriangleMeshShape*> & m_overlapShapes;
  296. public:
  297. PhysSceneMeshesReport(array<NxTriangleMeshShape*> & overlapShapes) :
  298. m_overlapShapes(overlapShapes)
  299. {
  300. m_overlapShapes.Empty();
  301. }
  302. virtual bool onEvent(NxU32 nbEntities, NxShape * * entities)
  303. {
  304. for (NxU32 i=0; i<nbEntities; i++)
  305. {
  306. NxTriangleMeshShape * shape = entities[i]->isTriangleMesh();
  307. if (shape)
  308. m_overlapShapes.Add(shape);
  309. }
  310. return true;
  311. }
  312. };
  313. class PhysSceneTrianglesReport : public NxUserEntityReport<NxU32>
  314. {
  315. private:
  316. // ссылка на массив куда сохраняются треугольники(просто друг за другом)
  317. array<Vector> & m_triangles;
  318. // ссылка на массив куда сохраняются материалы треугольников(просто друг за другом)
  319. array<PhysTriangleMaterialID> * m_trianglesMaterials;
  320. // Меш с которого берутся и тестятся эти треугольники
  321. NxTriangleMeshShape & m_meshShape;
  322. public:
  323. PhysSceneTrianglesReport(array<Vector> & triangles, array<PhysTriangleMaterialID> * trianglesMaterials, NxTriangleMeshShape & meshShape) :
  324. m_triangles(triangles),
  325. m_trianglesMaterials(trianglesMaterials),
  326. m_meshShape(meshShape)
  327. {
  328. }
  329. virtual bool onEvent(NxU32 nbEntities, NxU32 * entities)
  330. {
  331. NxMaterialIndex shape_mtl = m_meshShape.getMaterial();
  332. NxTriangleMesh & mesh = m_meshShape.getTriangleMesh();
  333. for (NxU32 i=0; i<nbEntities; i++)
  334. {
  335. NxTriangle trg;
  336. m_meshShape.getTriangle(trg, null, null, entities[i], true, true);
  337. for (long j=0; j<3; j++)
  338. m_triangles.Add(Nx(trg.verts[j]));
  339. // если есть массив с материалами
  340. if (m_trianglesMaterials)
  341. {
  342. NxMaterialIndex material = mesh.getTriangleMaterial(entities[i]);
  343. if (material != 0xFFFF)
  344. m_trianglesMaterials->Add((PhysTriangleMaterialID)material);
  345. else
  346. m_trianglesMaterials->Add((PhysTriangleMaterialID)shape_mtl);
  347. }
  348. }
  349. return true;
  350. }
  351. };
  352. // Тестит формы на пересечении со сферой, возвращает объект в котором куча треугольников, или null если ничего нету
  353. bool PhysicsScene::OverlapSphere(const Vector & pos, float radius, dword mask, bool staticShapes, bool dynamicShapes, array<Vector> & aTriangles, array<PhysTriangleMaterialID> * aTriangleMaterials)
  354. {
  355. NxSphere nxSphere(Nx(pos), radius);
  356. int nxShapeType = 0;
  357. if (staticShapes) nxShapeType |= NX_STATIC_SHAPES;
  358. if (dynamicShapes) nxShapeType |= NX_DYNAMIC_SHAPES;
  359. if (!nxShapeType)
  360. return false;
  361. // находим меши которые пересекаются со сферой
  362. PhysSceneMeshesReport reportMeshes(m_OverlapShapes);
  363. m_scene->overlapSphereShapes(nxSphere, NxShapesType(nxShapeType), 0, null, &reportMeshes, mask, null, false);
  364. // тестим выбранные меши на треугольники
  365. aTriangles.Empty();
  366. if (aTriangleMaterials)
  367. aTriangleMaterials->Empty();
  368. NxBounds3 bounds;
  369. bounds.set(Nx(pos - radius), Nx(pos + radius));
  370. for (long i=0; i<m_OverlapShapes; i++)
  371. {
  372. PhysSceneTrianglesReport reportTriangles(aTriangles, aTriangleMaterials, *m_OverlapShapes[i]);
  373. m_OverlapShapes[i]->overlapAABBTriangles(bounds, NX_QUERY_WORLD_SPACE, &reportTriangles);
  374. }
  375. return !aTriangles.IsEmpty();
  376. }
  377. //Тестит капсулу на пересечение с объектами, возвращает true если было пересечение
  378. bool PhysicsScene::CheckOverlapCapsule(const Vector & pos, float height, float radius, dword mask, bool staticShapes, bool dynamicShapes)
  379. {
  380. Vector h = Vector(0.0f, height * 0.5f, 0.0f);
  381. NxSegment seg(Nx(pos - h), Nx(pos + h));
  382. NxCapsule capsule(seg, radius);
  383. int nxShapeType = 0;
  384. if (staticShapes) nxShapeType |= NX_STATIC_SHAPES;
  385. if (dynamicShapes) nxShapeType |= NX_DYNAMIC_SHAPES;
  386. if (!nxShapeType)
  387. return false;
  388. bool result = m_scene->checkOverlapCapsule(capsule, NxShapesType(nxShapeType), mask);
  389. return result;
  390. }
  391. //-------------------------------------------------------------------------------------------------------------
  392. //Дополнительные функции
  393. //-------------------------------------------------------------------------------------------------------------
  394. //Трейс луча через все объекты
  395. IPhysBase * PhysicsScene::Raycast(const Vector & from, const Vector & to, dword mask, RaycastResult * detail)
  396. {
  397. //Направление
  398. Vector dir = to - from;
  399. float dist = dir.Normalize();
  400. //Луч
  401. NxRay ray;
  402. ray.orig = Nx(from);
  403. ray.dir = Nx(dir);
  404. //Трейсим луч
  405. NxRaycastHit hit;
  406. NxShape * shape = m_scene->raycastClosestShape(ray, NX_ALL_SHAPES, hit, mask, dist + 0.000001f);
  407. if(!shape) return null;
  408. if(detail)
  409. {
  410. detail->position = Nx(hit.worldImpact);
  411. detail->normal = Nx(hit.worldNormal);
  412. detail->distance = (float)hit.distance;
  413. detail->mtl = (MaterialID)hit.materialIndex;
  414. detail->id = shape->userData;
  415. }
  416. IPhysBase * physObj = (IPhysBase *)(shape->getActor().userData);
  417. if (physObj)
  418. {
  419. IPhysBase * proxyObj = physObj->GetProxyObject();
  420. if (proxyObj)
  421. return proxyObj;
  422. }
  423. return physObj;
  424. }
  425. //Текущий режим работы
  426. bool PhysicsScene::IsHardware()
  427. {
  428. return m_service->IsHardware();
  429. }
  430. bool PhysicsScene::IsMultiThreading()
  431. {
  432. return m_service->IsMultiThreading();
  433. }
  434. #ifndef STOP_DEBUG
  435. //Нарисовать отладочную информацию
  436. void PhysicsScene::DebugDraw(IRender & render)
  437. {
  438. m_debugDraw = true;
  439. }
  440. void PhysicsScene::RealDebugDraw()
  441. {
  442. if (!m_debugDraw) return;
  443. IRender & render = *(IRender *)api->GetService("DX9Render");
  444. const NxDebugRenderable * renderable = m_scene->getDebugRenderable();
  445. if(!renderable) return;
  446. const NxDebugRenderable & data = *renderable;
  447. render.SetWorld(Matrix());
  448. //Рисуем треугольники
  449. NxU32 count = data.getNbTriangles();
  450. const NxDebugTriangle * triangles = data.getTriangles();
  451. struct DrawTriVertex
  452. {
  453. Vector pos;
  454. dword color;
  455. } tbuffer[256*3];
  456. for(NxU32 i = 0, tc = 0; i < count; i++)
  457. {
  458. const NxDebugTriangle & trg = triangles[i];
  459. tbuffer[tc + 0].pos = Nx(trg.p0);
  460. tbuffer[tc + 0].color = trg.color;
  461. //tbuffer[tc + 0].color = 0xff00ff00;
  462. tbuffer[tc + 1].pos = Nx(trg.p1);
  463. tbuffer[tc + 1].color = trg.color;
  464. //tbuffer[tc + 1].color = 0xff00ff00;
  465. tbuffer[tc + 2].pos = Nx(trg.p2);
  466. tbuffer[tc + 2].color = trg.color;
  467. //tbuffer[tc + 2].color = 0xff00ff00;
  468. tc++;
  469. if(tc >= ARRSIZE(tbuffer)/3)
  470. {
  471. ShaderId id;
  472. render.GetShaderId("stdPolygon", id);
  473. render.DrawPrimitiveUP(id, PT_TRIANGLELIST, tc, tbuffer, sizeof(tbuffer[0]));
  474. tc = 0;
  475. }
  476. }
  477. if(tc > 0)
  478. {
  479. ShaderId id;
  480. render.GetShaderId("stdPolygon", id);
  481. render.DrawPrimitiveUP(id, PT_TRIANGLELIST, tc, tbuffer, sizeof(tbuffer[0]));
  482. }
  483. //Рисуем линии
  484. count = data.getNbLines();
  485. const NxDebugLine * lines = data.getLines();
  486. render.FlushBufferedLines();
  487. for(NxU32 i = 0; i < count; i++)
  488. {
  489. const NxDebugLine & line = lines[i];
  490. //render.DrawBufferedLine(Nx(line.p0), line.color, Nx(line.p1), line.color);
  491. render.DrawBufferedLine(Nx(line.p0), 0xff0000ff, Nx(line.p1), 0xff0000ff);
  492. }
  493. render.FlushBufferedLines();
  494. //Рисуем точки в виде пактиклов
  495. count = data.getNbPoints();
  496. const NxDebugPoint * points = data.getPoints();
  497. for(NxU32 i = 0; i < count; i++)
  498. {
  499. }
  500. // выходим из секции
  501. if (IsMultiThreading())
  502. {
  503. //m_SyncSection.Leave();
  504. }
  505. }
  506. #endif
  507. //Получить физическую сцену
  508. NxScene & PhysicsScene::Scene()
  509. {
  510. return *m_scene;
  511. }
  512. //Получить мэнеджер контролеров для персонажей
  513. NxControllerManager & PhysicsScene::CtrManager()
  514. {
  515. return m_service->CtrManager();
  516. }
  517. //Пересчитать состояние перед началом кадра
  518. void PhysicsScene::UpdateBeginFrame(float dltTime)
  519. {
  520. m_lastDeltaTime = dltTime;
  521. if (m_service->isStop) return;
  522. if (IsMultiThreading() && m_lastDeltaTime > 0.0f)
  523. {
  524. // стартуем выполнения физики в отдельном треде
  525. m_service->AddScene2Execute(this);
  526. //SetEvent(m_hSimulateStartEvent);
  527. }
  528. }
  529. void PhysicsScene::SimulationDone()
  530. {
  531. if (IsMultiThreading())
  532. SetEvent(m_hSimulateDoneEvent);
  533. }
  534. //Пересчитать состояние после кадра
  535. void PhysicsScene::UpdateEndFrame(float dltTime)
  536. {
  537. if (m_service->isStop) return;
  538. //if(dltTime > 0.1f) dltTime = 0.1f;
  539. // очищаем все контакты, потому что на fetchResult придут новые
  540. // обнуляем флажок контактов у всех объектов
  541. for (int i=0; i<m_objects.Len(); i++)
  542. m_objects[i]->SetContactReport(-1);
  543. if (!IsMultiThreading())
  544. {
  545. if (dltTime > 0.0f)
  546. {
  547. m_scene->simulate((NxReal)dltTime);
  548. m_scene->flushStream();
  549. NxU32 uErrorCode = 0;
  550. m_scene->fetchResults(NX_RIGID_BODY_FINISHED, true, &uErrorCode );
  551. }
  552. ExecuteProxies(m_proxies);
  553. ExecuteProxies(m_clothproxies);
  554. ExecuteProxies(m_conproxies);
  555. CtrManager().updateControllers();
  556. }
  557. else
  558. {
  559. // ждем эвента на старте выполнения треда
  560. if (m_lastDeltaTime > 0.0f)
  561. {
  562. // ждем окончания выполнения Simulate
  563. WaitForSingleObject(m_hSimulateDoneEvent, INFINITE);
  564. m_scene->fetchResults(NX_RIGID_BODY_FINISHED, true);
  565. }
  566. ExecuteProxies(m_proxies);
  567. ExecuteProxies(m_clothproxies);
  568. ExecuteProxies(m_conproxies);
  569. CtrManager().updateControllers();
  570. }
  571. // нормализуем 1 объект в кадр
  572. int normalizeCount = (m_objects.Size() + 15) / 16;
  573. int normalized = 0;
  574. while (normalizeCount && normalized < 5)
  575. {
  576. if (m_normalizeObjectIndex >= m_objects.Size())
  577. m_normalizeObjectIndex = 0;
  578. IPhysBase * realObject = m_objects[m_normalizeObjectIndex]->GetRealObject();
  579. if (realObject)
  580. normalized += realObject->Normalize();
  581. m_normalizeObjectIndex++;
  582. normalizeCount--;
  583. }
  584. #ifndef STOP_DEBUG
  585. DebugFrame();
  586. if (m_debugDraw)
  587. RealDebugDraw();
  588. #endif
  589. }
  590. void PhysicsScene::ExecuteProxies(array<IProxy*> & proxies)
  591. {
  592. for (unsigned int i = 0; i < proxies.Size(); i++)
  593. proxies[i]->OnSyncCreate();
  594. for (unsigned int i = 0; i < proxies.Size(); i++)
  595. proxies[i]->OnSyncCalls();
  596. for (unsigned int i = 0; i < proxies.Size(); i++)
  597. {
  598. if (proxies[i]->OnSyncRelease())
  599. {
  600. i--;
  601. }
  602. }
  603. }
  604. void PhysicsScene::UnregistryPhysObject(IPhysBase * obj)
  605. {
  606. // FIX-ME: может быть стоит использовать ExtractNoShift?
  607. dword idx = m_objects.Find(obj);
  608. if (idx != INVALID_ARRAY_INDEX)
  609. {
  610. if (m_normalizeObjectIndex >= idx)
  611. m_normalizeObjectIndex = Min(m_normalizeObjectIndex - 1, m_objects.Size());
  612. m_objects.DelIndex(idx);
  613. }
  614. // удаляем из мешей
  615. m_meshes.Del(obj);
  616. }
  617. void PhysicsScene::UnregistryProxyObject(IProxy * obj)
  618. {
  619. // FIX-ME: может быть стоит использовать ExtractNoShift?
  620. //if (IsMultiThreading())
  621. {
  622. m_proxies.Del(obj);
  623. m_conproxies.Del(obj);
  624. m_clothproxies.Del(obj);
  625. }
  626. }
  627. #ifndef STOP_DEBUG
  628. //Ищем прокси объект с данным актером
  629. IProxy * PhysicsScene::FindProxyObject(NxActor * actor)
  630. {
  631. #ifndef _XBOX
  632. for (long i=0; i<m_proxies; i++)
  633. {
  634. try
  635. {
  636. PhysInternal internals;
  637. IPhysRigidBody * rigid_body = dynamic_cast<IPhysRigidBody*>(m_proxies[i]);
  638. if (rigid_body)
  639. {
  640. rigid_body->GetInternals(internals);
  641. if (internals.actor == actor)
  642. return m_proxies[i];
  643. }
  644. }
  645. catch(...)
  646. {
  647. }
  648. }
  649. #endif
  650. return null;
  651. }
  652. #endif
  653. //Блокировка physx в мультитред режиме, если он что-то внутри делает, что сломает результаты не threadsafe функций
  654. void PhysicsScene::lockQueries()
  655. {
  656. if (!IsMultiThreading()) return;
  657. m_scene->lockQueries();
  658. }
  659. void PhysicsScene::unlockQueries()
  660. {
  661. if (!IsMultiThreading()) return;
  662. m_scene->unlockQueries();
  663. }
  664. void PhysicsScene::SceneChanged()
  665. {
  666. m_sceneChangedIndex++;
  667. }
  668. dword PhysicsScene::GetSceneChangedIndex()
  669. {
  670. return m_sceneChangedIndex;
  671. }
  672. void PhysicsScene::ContactReport::onContactNotify(NxContactPair & pair, NxU32 events)
  673. {
  674. Vector force = Nx(pair.sumNormalForce);
  675. if (pair.isDeletedActor[0] || pair.isDeletedActor[1])
  676. return;
  677. if (force.GetLength2() >= CONTACT_FORCE_THRESHOLD)
  678. {
  679. NxContactStreamIterator iter(pair.stream);
  680. while (iter.goNextPair())
  681. {
  682. //user can also call getShape() and getNumPatches() here
  683. NxShape * shape0 = iter.getShape(0);
  684. NxShape * shape1 = iter.getShape(1);
  685. IPhysBase * receiver = null;
  686. if (shape0)
  687. {
  688. NxActor & actor0 = shape0->getActor();
  689. receiver = (IPhysBase *)actor0.userData;
  690. }
  691. while (iter.goNextPatch())
  692. {
  693. while (iter.goNextPoint())
  694. {
  695. if (shape1 && receiver && receiver->GetContactReport() == -1)
  696. {
  697. NxTriangleMeshShape * shape = shape1->isTriangleMesh();
  698. // Достаем материал из меша
  699. if (shape)
  700. {
  701. NxTriangleMesh & mesh = shape->getTriangleMesh();
  702. NxInternalFormat fmt = mesh.getFormat(0, NX_ARRAY_TRIANGLES_REMAP);
  703. if (fmt == NX_FORMAT_INT && mesh.getSubmeshCount() == 1)
  704. {
  705. NxTriangleMesh & mesh = shape->getTriangleMesh();
  706. int * remap = (int *)mesh.getBase(0, NX_ARRAY_TRIANGLES_REMAP);
  707. int remapCounts = mesh.getCount(0, NX_ARRAY_TRIANGLES_REMAP);
  708. int trianglesCounts = mesh.getCount(0, NX_ARRAY_TRIANGLES);
  709. //if (remap && remapCounts < iter.getFeatureIndex1())
  710. {
  711. int trg_index = -1;
  712. int featureIndex1 = iter.getFeatureIndex1();
  713. if (remap)
  714. {
  715. if (featureIndex1 < remapCounts)
  716. trg_index = remap[featureIndex1];
  717. }
  718. else
  719. {
  720. if (featureIndex1 < trianglesCounts)
  721. trg_index = featureIndex1;
  722. }
  723. NxMaterialIndex mat = 0xFFFF;
  724. if (trg_index >= 0)
  725. mat = mesh.getTriangleMaterial(trg_index);
  726. if (mat == 0xFFFF)
  727. mat = shape->getMaterial();
  728. //NxActor & actor = shape0->getActor();
  729. if (mat != 0xFFFF)
  730. {
  731. receiver->SetContactReport(dword(mat));
  732. receiver->SetContactReportPoint(Nx(iter.getPoint()));
  733. receiver->SetContactReportForce(force);
  734. //m_scene->m_spheres.Add(Nx(iter.getPoint()));
  735. }
  736. }
  737. }
  738. }
  739. else
  740. { // Достаем материал из актера второго шейпа
  741. //NxMaterialIndex mat = shape1->getMaterial();
  742. NxActor & actor1 = shape1->getActor();
  743. IPhysRigidBody * collider = (IPhysRigidBody *)actor1.userData;
  744. if (collider)
  745. {
  746. receiver->SetContactReport(collider->GetMaterial());
  747. receiver->SetContactReportPoint(Nx(iter.getPoint()));
  748. receiver->SetContactReportForce(Nx(pair.sumNormalForce));
  749. //m_scene->m_spheres.Add(Nx(iter.getPoint()));
  750. }
  751. }
  752. }
  753. }
  754. }
  755. }
  756. }
  757. }