Phys Body.cpp 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. namespace EE{
  4. #include "PhysX Stream.h"
  5. /******************************************************************************
  6. 'PhysPart.base' muse not have quads (only triangles),
  7. because Bullet doesn't copy memory and uses only provided data.
  8. '_bullet_cooked_data' must be aligned to 16 bytes.
  9. PhysMesh may not be deleted while there are still actors using that mesh,
  10. that's why it uses 'used_by' reference count, and it will get deleted
  11. only when there are no references left.
  12. /******************************************************************************/
  13. #define CC4_PHSB CC4('P','H','S','B') // PhysBase (unused anymore)
  14. #define CC4_PHSP CC4('P','H','S','P') // PhysPart
  15. #define CC4_PHYS CC4('P','H','Y','S') // PhysBody
  16. #define CC4_PHSG CC4('P','H','S','G') // PhysGroup
  17. /******************************************************************************/
  18. DEFINE_CACHE(PhysBody, PhysBodies, PhysBodyPtr, "PhysBody");
  19. static Memx<PhysMesh> PhysMeshes;
  20. static SyncLock PhysMeshesLock;
  21. /******************************************************************************/
  22. void IncRef(PhysMesh* &pm) {if(pm)AtomicInc(pm->_used_by);}
  23. void DecRef(PhysMesh* &pm)
  24. {
  25. if(pm)
  26. {
  27. if(PhysMeshes.elms()) // if 'PhysMeshes' destructor was not yet called, and there are elements ('pm' is not pointing to already released memory)
  28. {
  29. AtomicDec(pm->_used_by);
  30. if(pm->_used_by< 0)Exit("PhysMesh has <0 references");
  31. if(pm->_used_by==0) // no longer used by any 'PhysBody' or 'Actor'
  32. {
  33. pm->del(); // delete it first, so it will not use 'Physics._lock' in destructor (deadlock could occur)
  34. {
  35. SafeSyncLocker locker(PhysMeshesLock);
  36. PhysMeshes.removeData(pm);
  37. }
  38. }
  39. }
  40. pm=null;
  41. }
  42. }
  43. void IncRef(btCollisionShape *shape)
  44. {
  45. if(shape)
  46. {
  47. SafeWriteLock lock(Physics._rws);
  48. IntPtr refs=(IntPtr)shape->getUserPointer();
  49. shape->setUserPointer(Ptr(refs+1));
  50. }
  51. }
  52. void DecRef(btCollisionShape *shape)
  53. {
  54. if(shape)
  55. {
  56. SafeWriteLock lock(Physics._rws);
  57. IntPtr refs=(IntPtr)shape->getUserPointer();
  58. if( refs< 0)Exit("btCollisionShape has <0 references");
  59. if( refs==0)Delete(shape);else shape->setUserPointer(Ptr(refs-1));
  60. }
  61. }
  62. static void Set(PhysMesh &pm, PhysMesh* &pm_ptr)
  63. {
  64. pm._used_by=1;
  65. PhysMeshesLock.on (); PhysMesh &stored_pm=PhysMeshes.New();
  66. PhysMeshesLock.off();
  67. Swap(stored_pm, pm);
  68. pm_ptr=&stored_pm;
  69. }
  70. /******************************************************************************/
  71. // PHYSICAL MESH
  72. /******************************************************************************/
  73. void PhysMesh::zero()
  74. {
  75. _type=PHYS_NONE;
  76. _box.zero();
  77. _base=null;
  78. _used_by=0;
  79. _bullet_cooked_data =null;
  80. _bullet_cooked_data_size=0;
  81. _convex=null;
  82. _mesh =null;
  83. _tvia =null;
  84. }
  85. void PhysMesh::del()
  86. {
  87. if(_convex || _mesh || _tvia) // delete API specific data first (because they may be dependent on data listed below)
  88. {
  89. SafeWriteLock lock(Physics._rws);
  90. #if PHYSX
  91. if(_convex && Physx.physics)_convex->release();
  92. if(_mesh && Physx.physics)_mesh ->release();
  93. #else
  94. DecRef(_convex); _convex=null;
  95. DecRef(_mesh ); _mesh =null;
  96. Delete(_tvia );
  97. #endif
  98. }
  99. Delete(_base);
  100. _physx_cooked_data.del();
  101. AlignedFree(_bullet_cooked_data);
  102. zero();
  103. }
  104. /******************************************************************************/
  105. void PhysMesh::freeHelperData()
  106. {
  107. #if PHYSX
  108. AlignedFree(_bullet_cooked_data); _bullet_cooked_data_size=0;
  109. if(_convex || _mesh ){Delete(_base); _physx_cooked_data.del();}else // delete helpers only if we've created data from them
  110. if(_physx_cooked_data.elms()){Delete(_base);}
  111. #else
  112. _physx_cooked_data.del();
  113. // don't delete '_base' and '_bullet_cooked_data' since Bullet Phys Meshes uses them (bullet mesh vtx/tri is directly mapped to '_base', while '_bullet_cooked_data' contains some extra precomputed data)
  114. #endif
  115. }
  116. /******************************************************************************/
  117. Bool PhysMesh::adjustStorage(Bool universal, Bool physx, Bool bullet, Bool *changed)
  118. {
  119. if(changed)*changed=false;
  120. if(_type==PHYS_CONVEX || _type==PHYS_MESH)
  121. {
  122. if( bullet)universal=true; // 'universal' is always needed when using 'bullet'
  123. if(!universal && !physx && !bullet)universal=true; // if no storage is specified then keep 'universal' only
  124. // create universal
  125. if(universal && !_base)
  126. {
  127. #if PHYSX
  128. setPhysMesh(); // create PhysX data if not yet available
  129. if(_convex){if(New(_base)->create(*_convex)){_base->quadToTri(); if(changed)*changed=true;}else Delete(_base);}else
  130. if(_mesh ){if(New(_base)->create(*_mesh )){_base->quadToTri(); if(changed)*changed=true;}else Delete(_base);}
  131. #endif
  132. }
  133. // create physx
  134. if(physx && !_physx_cooked_data.elms() && _base)switch(_type)
  135. {
  136. case PHYS_CONVEX: if(cookConvex(_base, true))if(changed)*changed=true; break;
  137. case PHYS_MESH : if(cookMesh (_base ))if(changed)*changed=true; break;
  138. }
  139. // create bullet
  140. if(bullet && _type==PHYS_MESH && !_bullet_cooked_data)
  141. {
  142. btOptimizedBvh *temp_bvh =null; // does not need to be released (as it's part of the mesh)
  143. btBvhTriangleMeshShape *temp_mesh=null;
  144. btTriangleIndexVertexArray *temp_tvia=null;
  145. if(!temp_bvh)
  146. {
  147. #if !PHYSX
  148. if(_mesh)temp_bvh=_mesh->getOptimizedBvh(); // check if bullet mesh has already pre-computed data
  149. #endif
  150. if(!temp_bvh && _base)
  151. {
  152. // create temp mesh when not available
  153. temp_tvia=new btTriangleIndexVertexArray(_base->tris(), (int*)_base->tri.ind(), SIZE(VecI), _base->vtxs(), (Flt*)_base->vtx.pos(), SIZE(Vec));
  154. temp_mesh=new btBvhTriangleMeshShape (temp_tvia, true, true);
  155. temp_bvh =temp_mesh->getOptimizedBvh();
  156. }
  157. }
  158. if(temp_bvh)
  159. {
  160. if(changed)*changed=true;
  161. if(_bullet_cooked_data_size=temp_bvh->calculateSerializeBufferSize())
  162. {
  163. _bullet_cooked_data=AlignedAlloc(_bullet_cooked_data_size);
  164. if( !temp_bvh->serializeInPlace(_bullet_cooked_data, _bullet_cooked_data_size, false))
  165. {
  166. AlignedFree(_bullet_cooked_data);
  167. _bullet_cooked_data_size=0;
  168. }
  169. }
  170. }
  171. Delete(temp_mesh);
  172. Delete(temp_tvia);
  173. }
  174. // then delete all unwanted
  175. if(!universal && _physx_cooked_data.elms() && _base ){Delete(_base); if(changed)*changed=true;} // delete only if there's physx left (don't delete if there's no physx )
  176. if(!physx && _base && _physx_cooked_data.elms()){ _physx_cooked_data.del(); if(changed)*changed=true;} // delete only if there's universal left (don't delete if there's no universal)
  177. if(!bullet && _bullet_cooked_data ){AlignedFree(_bullet_cooked_data); _bullet_cooked_data_size=0; if(changed)*changed=true;}
  178. // check for failure
  179. if((!universal)!=(! _base ))return false;
  180. if((!physx )!=(! _physx_cooked_data.elms()))return false;
  181. if(_type==PHYS_MESH)if((!bullet )!=(!_bullet_cooked_data ))return false; // only PHYS_MESH uses 'bullet' data
  182. }
  183. return true;
  184. }
  185. /******************************************************************************/
  186. Bool PhysMesh::cookConvex(MeshBase *src, Bool mesh_is_already_convex) // cook data only if the body doesn't have yet any cooked data
  187. {
  188. #if PHYSX
  189. if(!_physx_cooked_data.elms() && src && src->vtxs())
  190. {
  191. PxConvexMeshDesc desc;
  192. Memt<PxHullPolygon, 32768> polys; // must be outside braces
  193. Memt<Byte , 32768> ind ; // must be outside braces
  194. desc.points.data =src->vtx.pos();
  195. desc.points.count =src->vtxs();
  196. desc.points.stride=SIZE(Vec);
  197. if(mesh_is_already_convex && src->faces())
  198. {
  199. Bool bit16=(src->vtxs()<=0x10000);
  200. desc.indices.data =src->tri.ind();
  201. desc.indices.count =src->tris()*3 + src->quads()*4;
  202. desc.indices.stride=(bit16 ? SIZE(U16) : SIZE(U32));
  203. if(bit16 || src->quads())
  204. {
  205. desc.indices.data=ind.setNum(desc.indices.count*desc.indices.stride).data();
  206. if(bit16)
  207. {
  208. Copy32To16((Byte*)desc.indices.data , src->tri .ind(), src->tris ()*3);
  209. Copy32To16((Byte*)desc.indices.data+src->tris()*(3*SIZE(U16)), src->quad.ind(), src->quads()*4);
  210. }else
  211. {
  212. Copy32To32((Byte*)desc.indices.data , src->tri .ind(), src->tris ()*3);
  213. Copy32To32((Byte*)desc.indices.data+src->tris()*(3*SIZE(U32)), src->quad.ind(), src->quads()*4);
  214. }
  215. }
  216. polys.setNum(src->faces());
  217. C Vec *pos=src->vtx.pos();
  218. Int offset=0;
  219. FREPA(polys)
  220. {
  221. PxHullPolygon &poly=polys[i];
  222. VecI p; // we can access quads as VecI too
  223. if(bit16)p=*(VecUS*)((U16*)desc.indices.data+offset);
  224. else p=*(VecI *)((U32*)desc.indices.data+offset);
  225. C Vec &p0=pos[p.x], &p1=pos[p.y], &p2=pos[p.z], n=GetNormal(p0, p1, p2);
  226. poly.mPlane[0]=n.x;
  227. poly.mPlane[1]=n.y;
  228. poly.mPlane[2]=n.z;
  229. poly.mPlane[3]=-Dot(p0, n);
  230. poly.mNbVerts =(InRange(i, src->tri) ? 3 : 4);
  231. poly.mIndexBase=offset; offset+=poly.mNbVerts;
  232. }
  233. desc.polygons.data =polys.data();
  234. desc.polygons.count =polys.elms();
  235. desc.polygons.stride=polys.elmSize();
  236. if(bit16)desc.flags|=PxConvexFlag::e16_BIT_INDICES;
  237. }else
  238. {
  239. desc.flags=PxConvexFlag::eCOMPUTE_CONVEX; // recompute the hull
  240. }
  241. OutputStream buf;
  242. if(!Physx.cook[0])Exit("PhysPart.createConvex\nPhysics hasn't been created");
  243. Physx.cook[0]->cookConvexMesh(desc, buf);
  244. if(!buf.data && !(desc.flags&PxConvexFlag::eCOMPUTE_CONVEX)) // if failed, then try to recompute the convex hull
  245. {
  246. FlagDisable(desc.flags, PxConvexFlag::e16_BIT_INDICES);
  247. FlagEnable (desc.flags, PxConvexFlag::eCOMPUTE_CONVEX);
  248. desc.polygons.data =null;
  249. desc.polygons.count =0;
  250. desc.polygons.stride=0;
  251. desc.indices .data =null;
  252. desc.indices .count =0;
  253. desc.indices .stride=0;
  254. Physx.cook[0]->cookConvexMesh(desc, buf);
  255. }
  256. _physx_cooked_data.setFrom(buf.data, buf.pos);
  257. }
  258. #endif
  259. return _physx_cooked_data.elms()!=0;
  260. }
  261. /******************************************************************************/
  262. Bool PhysMesh::cookMesh(MeshBase *src, Bool keep_face_indexes) // cook data only if the body doesn't have yet any cooked data
  263. {
  264. #if PHYSX
  265. if(!_physx_cooked_data.elms() && src && src->vtxs() && src->faces())
  266. {
  267. PxTriangleMeshDesc desc;
  268. Memt<Byte> ind; // must be outside braces
  269. Bool bit16=(src->vtxs()<=0x10000);
  270. desc.triangles.stride=(bit16 ? SIZE(U16)*3 : SIZE(U32)*3);
  271. desc.triangles.count =src->trisTotal();
  272. desc.triangles.data =src->tri.ind();
  273. if(bit16 || src->quads())
  274. {
  275. desc.triangles.data=ind.setNum(desc.triangles.count*desc.triangles.stride).data();
  276. SetFaceIndex((Ptr)desc.triangles.data, src->tri.ind(), src->tris(), src->quad.ind(), src->quads(), bit16);
  277. }
  278. desc.points.data =src->vtx.pos();
  279. desc.points.count =src->vtxs();
  280. desc.points.stride=SIZE(Vec);
  281. if(bit16)desc.flags|=PxMeshFlag::e16_BIT_INDICES;
  282. OutputStream buf;
  283. if(!Physx.cook[keep_face_indexes])Exit("PhysPart.createMesh\nPhysics hasn't been created");
  284. Physx.cook[keep_face_indexes]->cookTriangleMesh(desc, buf);
  285. _physx_cooked_data.setFrom(buf.data, buf.pos);
  286. }
  287. #endif
  288. return _physx_cooked_data.elms()!=0;
  289. }
  290. /******************************************************************************
  291. Bool PhysMesh::cookHeightfield(MeshBase *src, Flt extent)
  292. {
  293. #if PHYSX
  294. #endif
  295. return _physx_cooked_data.elms()!=0;
  296. }
  297. /******************************************************************************/
  298. void PhysMesh::setPhysMesh()
  299. {
  300. #if PHYSX
  301. switch(_type)
  302. {
  303. case PHYS_CONVEX: if(!_convex){WriteLock lock(Physics._rws); if(!_convex && Physx.physics && cookConvex(_base, true)){InputStream is(_physx_cooked_data.data(), _physx_cooked_data.elms()); _convex=Physx.physics->createConvexMesh (is);}} break;
  304. case PHYS_MESH : if(!_mesh ){WriteLock lock(Physics._rws); if(!_mesh && Physx.physics && cookMesh (_base )){InputStream is(_physx_cooked_data.data(), _physx_cooked_data.elms()); _mesh =Physx.physics->createTriangleMesh(is);}} break;
  305. }
  306. #else
  307. if(_base)switch(_type)
  308. {
  309. case PHYS_CONVEX: if(!_convex){WriteLock lock(Physics._rws); if(!_convex)if(_convex=new btConvexHullShape((Flt*)_base->vtx.pos(), _base->vtxs(), SIZE(Vec)))_convex->setMargin(Physics.skin());} break;
  310. case PHYS_MESH : if(!_mesh ){WriteLock lock(Physics._rws); if(!_mesh )
  311. {
  312. _tvia=new btTriangleIndexVertexArray(_base->tris(), (Int*)_base->tri.ind(), SIZE(VecI), _base->vtxs(), (Flt*)_base->vtx.pos(), SIZE(Vec));
  313. _mesh=new btBvhTriangleMeshShape (_tvia, true, false);
  314. if( _bullet_cooked_data )_mesh-> setOptimizedBvh(btOptimizedBvh::deSerializeInPlace(_bullet_cooked_data, _bullet_cooked_data_size, false));
  315. if(!_mesh->getOptimizedBvh())_mesh->buildOptimizedBvh();
  316. _mesh->setMargin(Physics.skin());
  317. }}
  318. break;
  319. }
  320. #endif
  321. if(App.flag&APP_AUTO_FREE_PHYS_BODY_HELPER_DATA)freeHelperData(); // after creating phys mesh we can try releasing helper data
  322. }
  323. /******************************************************************************/
  324. Bool PhysMesh::createConvexTry(MeshBase &mshb, Bool mesh_is_already_convex)
  325. {
  326. del();
  327. if(mshb.vtxs())
  328. {
  329. #if PHYSX
  330. if(!cookConvex(&mshb, mesh_is_already_convex))return false;
  331. #else
  332. New(_base);
  333. if(mesh_is_already_convex)_base->create (mshb , 0).quadToTri();
  334. else _base->createConvex(mshb.vtx.pos(), mshb.vtxs()).quadToTri();
  335. #endif
  336. T._type=PHYS_CONVEX;
  337. mshb.getBox(T._box);
  338. setPhysMesh();
  339. }
  340. return true;
  341. }
  342. /******************************************************************************/
  343. Bool PhysMesh::createMeshTry(MeshBase &mshb, Bool keep_face_indexes)
  344. {
  345. del();
  346. if(mshb.vtxs() && mshb.faces())
  347. {
  348. #if PHYSX
  349. if(!cookMesh(&mshb, keep_face_indexes))return false;
  350. #else
  351. New(_base)->create(mshb, 0).quadToTri();
  352. #endif
  353. T._type=PHYS_MESH;
  354. mshb.getBox(T._box);
  355. setPhysMesh();
  356. }
  357. return true;
  358. }
  359. /******************************************************************************/
  360. #if !PHYSX
  361. Flt PhysMesh::volume()C
  362. {
  363. if(_base)return _base->convexVolume();
  364. if(_convex) // approximate with a Ball
  365. {
  366. btVector3 center; btScalar radius; _convex->getBoundingSphere(center, radius);
  367. return Ball(radius).volume();
  368. }
  369. return 0;
  370. }
  371. #endif
  372. Bool PhysMesh::setBox()
  373. {
  374. switch(_type)
  375. {
  376. case PHYS_CONVEX:
  377. {
  378. if(_base)return _base->getBox(_box);
  379. #if PHYSX
  380. if(_convex){_box=Physx.box(_convex->getLocalBounds()); return true;}
  381. #else
  382. if(_convex){btVector3 min, max; _convex->getAabb(btTransform::getIdentity(), min, max); _box.set(Bullet.vec(min), Bullet.vec(max)); return true;}
  383. #endif
  384. }break;
  385. case PHYS_MESH:
  386. {
  387. if(_base)return _base->getBox(_box);
  388. #if PHYSX
  389. if(_mesh){_box=Physx.box(_mesh->getLocalBounds()); return true;}
  390. #else
  391. if(_mesh){btVector3 min, max; _mesh->getAabb(btTransform::getIdentity(), min, max); _box.set(Bullet.vec(min), Bullet.vec(max)); return true;}
  392. #endif
  393. }break;
  394. }
  395. _box.zero(); return false;
  396. }
  397. /******************************************************************************/
  398. void PhysMesh::draw(C Color &color)C
  399. {
  400. switch(_type)
  401. {
  402. case PHYS_CONVEX: if(_base)DrawPhys(*_base, color);else if(_convex)DrawConvex(*_convex, color); break;
  403. case PHYS_MESH : if(_base)DrawPhys(*_base, color);else if(_mesh )DrawMesh (*_mesh , color); break;
  404. }
  405. }
  406. PhysMesh& PhysMesh::operator=(C PhysMesh &src)
  407. {
  408. if(this!=&src)
  409. {
  410. del();
  411. _type=src._type;
  412. _box =src._box;
  413. if(src._base)New(_base)->create(*src._base);
  414. _physx_cooked_data=src._physx_cooked_data;
  415. if(src._bullet_cooked_data)
  416. {
  417. _bullet_cooked_data_size= src._bullet_cooked_data_size;
  418. _bullet_cooked_data =AlignedAlloc(_bullet_cooked_data_size);
  419. CopyFast(_bullet_cooked_data, src._bullet_cooked_data, _bullet_cooked_data_size);
  420. }
  421. #if PHYSX
  422. if(!_base && !_physx_cooked_data.elms()) // if we don't have any phys, but src has phys mesh (this can happen if 'freeHelperData' was called)
  423. {
  424. if(src._convex){New(_base)->create(*src._convex); setPhysMesh(); Delete(_base); if(_convex)_physx_cooked_data.del();} // try creating from phys mesh
  425. if(src._mesh ){New(_base)->create(*src._mesh ); setPhysMesh(); Delete(_base); if(_mesh )_physx_cooked_data.del();} // try creating from phys mesh
  426. }
  427. #endif
  428. setPhysMesh();
  429. }
  430. return T;
  431. }
  432. /******************************************************************************/
  433. // PHYSICAL BODY PART
  434. /******************************************************************************/
  435. void PhysPart::zero()
  436. {
  437. density=0;
  438. _type =PHYS_NONE;
  439. _pm =null;
  440. }
  441. PhysPart::PhysPart( ) {zero(); }
  442. PhysPart::PhysPart(C Box &box , Flt density) {zero(); create(box , density);}
  443. PhysPart::PhysPart(C OBox &obox , Flt density) {zero(); create(obox , density);}
  444. PhysPart::PhysPart(C Extent &ext , Flt density) {zero(); create(ext , density);}
  445. PhysPart::PhysPart(C Ball &ball , Flt density) {zero(); create(ball , density);}
  446. PhysPart::PhysPart(C Capsule &capsule, Flt density) {zero(); create(capsule, density);}
  447. PhysPart::PhysPart(C Tube &tube , Flt density) {zero(); create(tube , density);}
  448. PhysPart::PhysPart(C Shape &shape , Flt density) {zero(); create(shape , density);}
  449. PhysPart& PhysPart::del()
  450. {
  451. DecRef(_pm);
  452. shape.type=SHAPE_NONE;
  453. zero(); return T;
  454. }
  455. PhysPart& PhysPart::create(C Shape &shape, Flt density)
  456. {
  457. del();
  458. T._type =PHYS_SHAPE;
  459. T. shape =shape;
  460. T. density=density;
  461. return T;
  462. }
  463. /******************************************************************************/
  464. Bool PhysPart::createConvexTry(MeshBase &mshb, Flt density, Bool mesh_is_already_convex)
  465. {
  466. del();
  467. if(mshb.vtxs())
  468. {
  469. PhysMesh pm; if(!pm.createConvexTry(mshb, mesh_is_already_convex))return false;
  470. Set(pm, T._pm);
  471. T._type =PHYS_CONVEX;
  472. T. density=density;
  473. }
  474. return true;
  475. }
  476. Bool PhysPart::createMeshTry(MeshBase &mshb, Bool keep_face_indexes)
  477. {
  478. del();
  479. if(mshb.vtxs() && mshb.faces())
  480. {
  481. PhysMesh pm; if(!pm.createMeshTry(mshb, keep_face_indexes))return false;
  482. Set(pm, T._pm);
  483. T._type =PHYS_MESH;
  484. T. density=1;
  485. }
  486. return true;
  487. }
  488. /******************************************************************************/
  489. Bool PhysPart::createConvexTry(MeshLod &mshl, Flt density, Bool mesh_is_already_convex, Bool skip_hidden_parts)
  490. {
  491. MeshBase mshb; mshb.createPhys(mshl, VTX_POS|FACE_IND, false, skip_hidden_parts);
  492. return createConvexTry(mshb, density, mesh_is_already_convex);
  493. }
  494. Bool PhysPart::createMeshTry(MeshLod &mshl, Bool keep_face_indexes, Bool skip_hidden_parts)
  495. {
  496. MeshBase mshb; mshb.createPhys(mshl, VTX_POS|FACE_IND, false, skip_hidden_parts);
  497. return createMeshTry(mshb, keep_face_indexes);
  498. }
  499. /******************************************************************************/
  500. PhysPart& PhysPart::createConvex(MeshBase &mshb, Flt density, Bool mesh_is_already_convex ) {if(!createConvexTry(mshb, density, mesh_is_already_convex ))Exit("PhysPart::createConvex"); return T;}
  501. PhysPart& PhysPart::createConvex(MeshLod &mshl, Flt density, Bool mesh_is_already_convex, Bool skip_hidden_parts) {if(!createConvexTry(mshl, density, mesh_is_already_convex, skip_hidden_parts))Exit("PhysPart::createConvex"); return T;}
  502. PhysPart& PhysPart::createMesh(MeshBase &mshb, Bool keep_face_indexes ) {if(!createMeshTry(mshb, keep_face_indexes ))Exit("PhysPart.createMesh"); return T;}
  503. PhysPart& PhysPart::createMesh(MeshLod &mshl, Bool keep_face_indexes, Bool skip_hidden_parts) {if(!createMeshTry(mshl, keep_face_indexes, skip_hidden_parts))Exit("PhysPart.createMesh"); return T;}
  504. /******************************************************************************/
  505. PhysPart& PhysPart::operator=(C PhysPart &src)
  506. {
  507. if(this!=&src)
  508. {
  509. del();
  510. density=src. density;
  511. shape =src. shape;
  512. _type =src._type;
  513. if(src._pm)
  514. {
  515. PhysMesh pm; pm=*src._pm;
  516. Set(pm, T._pm);
  517. }
  518. }
  519. return T;
  520. }
  521. /******************************************************************************/
  522. Flt PhysPart::area ( )C {return (_type==PHYS_SHAPE) ? shape.area () : 0;}
  523. Flt PhysPart::volume( )C {return (_type==PHYS_SHAPE) ? shape.volume() : 0;}
  524. Bool PhysPart::getBox(Box &box)C
  525. {
  526. switch(_type)
  527. {
  528. case PHYS_SHAPE: box=shape; return true;
  529. case PHYS_CONVEX:
  530. case PHYS_MESH : if(_pm){box=_pm->_box; return true;} break;
  531. }
  532. box.zero(); return false;
  533. }
  534. /******************************************************************************/
  535. PhysPart& PhysPart::transform(C Matrix3 &matrix)
  536. {
  537. switch(_type)
  538. {
  539. case PHYS_SHAPE : shape*=matrix; break;
  540. case PHYS_CONVEX: {MeshBase temp; temp.create(T); temp.transform(matrix); createConvex(temp, density, true);} break;
  541. case PHYS_MESH : {MeshBase temp; temp.create(T); temp.transform(matrix); createMesh (temp );} break;
  542. }
  543. return T;
  544. }
  545. PhysPart& PhysPart::transform(C Matrix &matrix)
  546. {
  547. switch(_type)
  548. {
  549. case PHYS_SHAPE : shape*=matrix; break;
  550. case PHYS_CONVEX: {MeshBase temp; temp.create(T); temp.transform(matrix); createConvex(temp, density, true);} break;
  551. case PHYS_MESH : {MeshBase temp; temp.create(T); temp.transform(matrix); createMesh (temp );} break;
  552. }
  553. return T;
  554. }
  555. /******************************************************************************/
  556. PhysPart& PhysPart::mirrorX()
  557. {
  558. switch(_type)
  559. {
  560. case PHYS_SHAPE : shape.mirrorX(); break;
  561. case PHYS_CONVEX: {MeshBase temp; temp.create(T); temp.mirrorX(); createConvexTry(temp, density, true);} break;
  562. case PHYS_MESH : {MeshBase temp; temp.create(T); temp.mirrorX(); createMeshTry (temp );} break;
  563. }
  564. return T;
  565. }
  566. PhysPart& PhysPart::mirrorY()
  567. {
  568. switch(_type)
  569. {
  570. case PHYS_SHAPE : shape.mirrorY(); break;
  571. case PHYS_CONVEX: {MeshBase temp; temp.create(T); temp.mirrorY(); createConvexTry(temp, density, true);} break;
  572. case PHYS_MESH : {MeshBase temp; temp.create(T); temp.mirrorY(); createMeshTry (temp );} break;
  573. }
  574. return T;
  575. }
  576. PhysPart& PhysPart::mirrorZ()
  577. {
  578. switch(_type)
  579. {
  580. case PHYS_SHAPE : shape.mirrorZ(); break;
  581. case PHYS_CONVEX: {MeshBase temp; temp.create(T); temp.mirrorZ(); createConvexTry(temp, density, true);} break;
  582. case PHYS_MESH : {MeshBase temp; temp.create(T); temp.mirrorZ(); createMeshTry (temp );} break;
  583. }
  584. return T;
  585. }
  586. /******************************************************************************/
  587. void PhysPart::setPhysMesh() {if(_pm)_pm->setPhysMesh();}
  588. /******************************************************************************/
  589. Bool PhysPart::adjustStorage(Bool universal, Bool physx, Bool bullet, Bool *changed)
  590. {
  591. if(_pm)
  592. {
  593. PhysPart temp; temp=T; Bool ok=temp._pm->adjustStorage(universal, physx, bullet, changed); Swap(temp, T); return ok; // adjust storage on separate 'pm' so any current actors using the mesh, will not get invalid
  594. }
  595. if(changed)*changed=false;
  596. return true;
  597. }
  598. /******************************************************************************/
  599. PhysPart& PhysPart::freeHelperData() {if(_pm)_pm->freeHelperData(); return T;}
  600. /******************************************************************************/
  601. void PhysPart::draw(C Color &color)C
  602. {
  603. switch(_type)
  604. {
  605. case PHYS_SHAPE: shape.draw(color); break;
  606. case PHYS_CONVEX:
  607. case PHYS_MESH : if(_pm)_pm->draw(color); break;
  608. }
  609. }
  610. /******************************************************************************/
  611. static Bool VerifyPhysX(File &f) // this function checks if provided PhysX cooked data is of the same version as currently used PhysX SDK
  612. {
  613. if(f.getUInt()==CC4('N', 'X', 'S', 1))switch(f.getUInt()) // type
  614. {
  615. case CC4('M','E','S','H'): // tri mesh
  616. {
  617. return f.getInt()==PHYS_API(PX_MESH_VERSION, -1); // this must be equal to the current version that PhysX SDK supports
  618. }break;
  619. case CC4('C','V','X','M'): // convex mesh
  620. {
  621. return f.getInt()==PHYS_API(PX_CONVEX_VERSION, -1); // this must be equal to the current version that PhysX SDK supports
  622. }break;
  623. }
  624. return false;
  625. }
  626. static Bool ImportPhysX(MeshBase &mesh, File &f) // import MeshBase from PhysX cooked data
  627. {
  628. if(f.getUInt()==CC4('N','X','S',1))switch(f.getUInt()) // type
  629. {
  630. case CC4('M','E','S','H'): // triangle mesh
  631. {
  632. switch(f.getInt()) // version
  633. {
  634. case 1: // PhysX 2.8.4
  635. {
  636. UInt flags=f.getUInt(); f.skip(4*3);
  637. Int vtxs =f.getInt ();
  638. Int tris =f.getInt ();
  639. if(vtxs>0 && tris>0)
  640. {
  641. mesh.create(vtxs, 0, tris, 0);
  642. f.getN(mesh.vtx.pos(), mesh.vtxs());
  643. if(flags& 8)FREPA(mesh.tri){VecB t; f>>t; mesh.tri.ind(i)=t;}else // 8-bit indexes
  644. if(flags&16)FREPA(mesh.tri){VecUS t; f>>t; mesh.tri.ind(i)=t;}else // 16-bit indexes
  645. f.getN(mesh.tri.ind(), mesh.tris()); // 32-bit indexes
  646. return true;
  647. }
  648. }break;
  649. case 9: // PhysX 3.2.2
  650. case 12: // PhysX 3.3.0
  651. {
  652. UInt flags;
  653. Flt unused;
  654. Int vtxs, tris;
  655. f.getMulti(flags, unused, vtxs, tris);
  656. if(vtxs>0 && tris>0)
  657. {
  658. mesh.create(vtxs, 0, tris, 0);
  659. f.getN(mesh.vtx.pos(), mesh.vtxs());
  660. if(flags&4)FREPA(mesh.tri){VecB t; f>>t; mesh.tri.ind(i)=t;}else // 8-bit indexes
  661. if(flags&8)FREPA(mesh.tri){VecUS t; f>>t; mesh.tri.ind(i)=t;}else // 16-bit indexes
  662. f.getN(mesh.tri.ind(), mesh.tris()); // 32-bit indexes
  663. return true;
  664. }
  665. }break;
  666. case 15: // PhysX 3.4.1
  667. {
  668. UInt midphaseID, flags;
  669. Int vtxs, tris;
  670. f.getMulti(midphaseID, flags, vtxs, tris);
  671. if(vtxs>0 && tris>0)
  672. {
  673. mesh.create(vtxs, 0, tris, 0);
  674. f.getN(mesh.vtx.pos(), mesh.vtxs());
  675. if(flags&4)FREPA(mesh.tri){VecB t; f>>t; mesh.tri.ind(i)=t;}else // 8-bit indexes
  676. if(flags&8)FREPA(mesh.tri){VecUS t; f>>t; mesh.tri.ind(i)=t;}else // 16-bit indexes
  677. f.getN(mesh.tri.ind(), mesh.tris()); // 32-bit indexes
  678. return true;
  679. }
  680. }break;
  681. #if PHYSX
  682. ASSERT(PX_MESH_VERSION==15); // if you get a compile error here, it means that support for the new format must be added above
  683. #endif
  684. }
  685. }break;
  686. case CC4('C','V','X','M'): // convex mesh
  687. {
  688. switch(f.getInt()) // version
  689. {
  690. case 3: // PhysX 2.8.4
  691. {
  692. f.getUInt();
  693. if(f.getUInt()==CC4('I','C','E', 1 ))
  694. if(f.getUInt()==CC4('C','L','H','L'))
  695. if(f.getInt ()==0)
  696. if(f.getUInt()==CC4('I','C','E', 1 ))
  697. if(f.getUInt()==CC4('C','V','H','L'))
  698. if(f.getInt ()==5)
  699. {
  700. Int vtxs=f.getInt();
  701. Int tris=f.getInt();
  702. if(vtxs>0 && vtxs<=256 && tris>0)
  703. {
  704. Int a=f.getInt();
  705. Int b=f.getInt();
  706. Int c=f.getInt();
  707. Int d=f.getInt();
  708. //if(c==2*a && c==d)
  709. {
  710. mesh.create(vtxs, 0, tris, 0);
  711. f.getN(mesh.vtx.pos(), mesh.vtxs());
  712. Int e=f.getInt();
  713. FREPA(mesh.tri){VecI &t=mesh.tri.ind(i); t.x=f.getByte(); t.y=f.getByte(); t.z=f.getByte();} // 8-bit indexes
  714. return true;
  715. }
  716. }
  717. }
  718. }break;
  719. case 13: // PhysX 3.2.2, 3.3.0, 3.4.1
  720. {
  721. f.getUInt();
  722. if(f.getUInt()==CC4('I','C','E', 1 ))
  723. if(f.getUInt()==CC4('C','L','H','L'))
  724. {
  725. Memt<VecI2> poly_data; // x=offset, y=vtxs
  726. Memt<Byte > ind;
  727. Int v=f.getInt();
  728. if( v==6)
  729. {
  730. if(f.getUInt()==CC4('I','C','E', 1 ))
  731. if(f.getUInt()==CC4('C','V','H','L'))
  732. if(f.getInt ()==6)
  733. {
  734. Int vtxs =f.getInt();
  735. Int a =f.getInt(); // this is NOT tris! (because it's different than what's calculated below)
  736. Int polys=f.getInt();
  737. Int inds =f.getInt();
  738. if(vtxs>0 && vtxs<=256 && polys>0 && inds>0)
  739. {
  740. mesh.create(vtxs, 0, 0, 0);
  741. f.getN(mesh.vtx.pos(), mesh.vtxs());
  742. UShort b=f.getUShort();
  743. Int tris=0;
  744. FREP(polys)
  745. {
  746. Vec4 v; f>>v;
  747. UShort offset=f.getUShort();
  748. Byte vtxs =f.getByte ();
  749. Byte a =f.getByte ();
  750. poly_data.New().set(offset, vtxs);
  751. tris+=Max(0, vtxs-2);
  752. }
  753. mesh.tri._elms=tris; mesh.include(TRI_IND);
  754. ind.setNum(inds); f.getN(ind.data(), ind.elms());
  755. tris=0;
  756. FREPA(poly_data)
  757. {
  758. C VecI2 &p=poly_data[i];
  759. Int offset=p.x, vtxs=p.y;
  760. FREP(vtxs-2)
  761. if(InRange(tris, mesh.tri))
  762. mesh.tri.ind(tris++).set(ind[offset+0], ind[offset+i+1], ind[offset+i+2]);
  763. }
  764. return true;
  765. }
  766. }
  767. }else
  768. if(v==7 || v==8) // 8=PhysX 3.4.1
  769. {
  770. if(f.getUInt()==CC4('I','C','E', 1 ))
  771. if(f.getUInt()==CC4('C','V','H','L'))
  772. if(f.getInt ()==v)
  773. {
  774. Int vtxs =f.getInt();
  775. Int a =f.getInt(); // this is NOT tris! (because it's different than what's calculated below)
  776. Int polys=f.getInt();
  777. Int inds =f.getInt();
  778. if(vtxs>0 && vtxs<=256 && polys>0 && inds>0)
  779. {
  780. mesh.create(vtxs, 0, 0, 0);
  781. f.getN(mesh.vtx.pos(), mesh.vtxs());
  782. Int tris=0;
  783. FREP(polys)
  784. {
  785. Vec4 v;
  786. UShort offset;
  787. Byte vtxs, a;
  788. f.getMulti(v, offset, vtxs, a);
  789. poly_data.New().set(offset, vtxs);
  790. tris+=Max(0, vtxs-2);
  791. }
  792. mesh.tri._elms=tris; mesh.include(TRI_IND);
  793. ind.setNum(inds); f.getN(ind.data(), ind.elms());
  794. tris=0;
  795. FREPA(poly_data)
  796. {
  797. C VecI2 &p=poly_data[i];
  798. Int offset=p.x, vtxs=p.y;
  799. FREP(vtxs-2)
  800. if(InRange(tris, mesh.tri))
  801. mesh.tri.ind(tris++).set(ind[offset+0], ind[offset+i+1], ind[offset+i+2]);
  802. }
  803. return true;
  804. }
  805. }
  806. }
  807. }
  808. }break;
  809. #if PHYSX
  810. ASSERT(PX_CONVEX_VERSION==13); // if you get a compile error here, it means that support for the new format must be added above
  811. #endif
  812. }
  813. }break;
  814. }
  815. return false;
  816. }
  817. static void Loaded(PhysMesh &pm)
  818. {
  819. if(pm._physx_cooked_data.elms())
  820. {
  821. #if PHYSX
  822. File f; f.readMem(pm._physx_cooked_data.data(), pm._physx_cooked_data.elms());
  823. if(!VerifyPhysX(f)) // if cooked version doesn't match with current PhysX SDK version
  824. {
  825. if(pm._base)pm._physx_cooked_data.del();else // if we have universal then just delete the incompatible physx cooked, and universal will be used
  826. {
  827. MeshBase temp;
  828. f.pos(0); if(ImportPhysX(temp, f)) // if import success
  829. {
  830. Swap(*New(pm._base), temp); // swap universal with temp
  831. pm._physx_cooked_data.del(); // delete cooked so universal will be used
  832. pm.setPhysMesh(); if(pm._mesh || pm._convex)Delete(pm._base); // if cooked and created PhysMesh successfully, then delete universal because we didn't want it originally
  833. }
  834. }
  835. }
  836. #else // bullet
  837. if(!pm._base) // try to import physx only if we don't have universal mesh
  838. {
  839. MeshBase temp;
  840. if(ImportPhysX(temp, File().readMem(pm._physx_cooked_data.data(), pm._physx_cooked_data.elms()))) // if import success
  841. Swap(*New(pm._base), temp); // swap universal with temp (keep physx cooked because it will not be used anyway, and we want to keep it in case of saving file)
  842. }
  843. #endif
  844. }
  845. pm.setPhysMesh();
  846. }
  847. Bool PhysPart::saveData(File &f)C
  848. {
  849. f.putMulti(Byte(4), _type, density); // version
  850. switch(_type)
  851. {
  852. case PHYS_NONE: return f.ok();
  853. case PHYS_SHAPE: return shape.save(f) && f.ok();
  854. case PHYS_CONVEX:
  855. case PHYS_MESH :
  856. {
  857. f<<_pm->_box;
  858. if(!_pm->_base)f.putBool(false);else{f.putBool(true); if(!_pm->_base->saveData(f))return false;}
  859. if(_pm->_physx_cooked_data._saveRaw(f))
  860. {
  861. if(!_pm->_bullet_cooked_data_size)f.cmpUIntV(0);else // bullet cooked data version, used in case future bullet cooked data will not be compatible, 0=no data, 1=current version
  862. {
  863. f.cmpUIntV(1); // version
  864. f<<_pm->_bullet_cooked_data_size;
  865. f.put(_pm->_bullet_cooked_data, _pm->_bullet_cooked_data_size);
  866. }
  867. return f.ok();
  868. }
  869. }break;
  870. }
  871. return false;
  872. }
  873. Bool PhysPart::loadData(File &f)
  874. {
  875. del(); switch(f.decUIntV()) // version
  876. {
  877. case 4:
  878. {
  879. f.getMulti(_type, density);
  880. switch(_type)
  881. {
  882. case PHYS_NONE: if(f.ok())return true; break;
  883. case PHYS_SHAPE: if(shape.load(f) && f.ok())return true; break;
  884. case PHYS_CONVEX:
  885. case PHYS_MESH :
  886. {
  887. PhysMesh pm; pm._type=_type;
  888. f>>pm._box;
  889. if(f.getBool())if(!New(pm._base)->loadData(f))goto error;
  890. if(pm._physx_cooked_data._loadRaw(f))
  891. {
  892. if(UInt bullet_ver=f.decUIntV())
  893. {
  894. if(bullet_ver!=1)f.skip(f.getUInt());else // other versions aren't supported
  895. {
  896. f>>pm._bullet_cooked_data_size;
  897. pm._bullet_cooked_data=AlignedAlloc(pm._bullet_cooked_data_size);
  898. f.get(pm._bullet_cooked_data, pm._bullet_cooked_data_size);
  899. }
  900. }
  901. if(f.ok())
  902. {
  903. Loaded(pm);
  904. Set(pm, T._pm);
  905. return true;
  906. }
  907. }
  908. }break;
  909. }
  910. }break;
  911. case 3:
  912. {
  913. f.getMulti(_type, density);
  914. switch(_type)
  915. {
  916. case PHYS_NONE: if(f.ok())return true; break;
  917. case PHYS_SHAPE: if(shape.load(f) && f.ok())return true; break;
  918. case PHYS_CONVEX:
  919. case PHYS_MESH :
  920. {
  921. PhysMesh pm; pm._type=_type;
  922. if(f.getBool())if(!New(pm._base)->loadData(f))goto error;
  923. if(pm._physx_cooked_data._loadRaw(f))
  924. {
  925. if(UInt bullet_ver=f.decUIntV())
  926. {
  927. if(bullet_ver!=1)f.skip(f.getUInt());else // other versions aren't supported
  928. {
  929. f>>pm._bullet_cooked_data_size;
  930. pm._bullet_cooked_data=AlignedAlloc(pm._bullet_cooked_data_size);
  931. f.get(pm._bullet_cooked_data, pm._bullet_cooked_data_size);
  932. }
  933. }
  934. if(f.ok())
  935. {
  936. Loaded(pm);
  937. pm.setBox();
  938. Set(pm, T._pm);
  939. return true;
  940. }
  941. }
  942. }break;
  943. }
  944. }break;
  945. case 2:
  946. {
  947. f.getMulti(_type, density);
  948. switch(_type)
  949. {
  950. case PHYS_NONE: if(f.ok())return true; break;
  951. case PHYS_SHAPE: if(shape.load(f) && f.ok())return true; break;
  952. case PHYS_CONVEX:
  953. case PHYS_MESH :
  954. {
  955. PhysMesh pm; pm._type=_type;
  956. if(f.getBool())if(!New(pm._base)->loadData(f))goto error;
  957. if(pm._physx_cooked_data._loadRaw(f))
  958. if(f.ok())
  959. {
  960. Loaded(pm);
  961. pm.setBox();
  962. Set(pm, T._pm);
  963. return true;
  964. }
  965. }break;
  966. }
  967. }break;
  968. case 1:
  969. {
  970. f.getMulti(_type, density);
  971. switch(_type)
  972. {
  973. case PHYS_NONE: if(f.ok())return true; break;
  974. case PHYS_SHAPE: if(shape.load(f) && f.ok())return true; break;
  975. case PHYS_CONVEX:
  976. case PHYS_MESH :
  977. {
  978. PhysMesh pm; pm._type=_type;
  979. if(pm._physx_cooked_data._loadRaw(f))
  980. if(f.ok())
  981. {
  982. Loaded(pm);
  983. pm.setBox();
  984. Set(pm, T._pm);
  985. return true;
  986. }
  987. }break;
  988. }
  989. }break;
  990. case 0:
  991. {
  992. Byte unused; f.getMulti(unused, _type, density);
  993. switch(_type)
  994. {
  995. case PHYS_NONE: if(f.ok())return true; break;
  996. case PHYS_SHAPE:
  997. {
  998. shape.type=SHAPE_TYPE(Byte(f.getUInt())); // needed, because in the past it was saved as raw memory
  999. Long pos=f.pos();
  1000. switch(shape.type)
  1001. {
  1002. default : goto error;
  1003. case SHAPE_NONE : break;
  1004. case SHAPE_POINT : f>>shape.point ; break;
  1005. case SHAPE_EDGE : f>>shape.edge ; break;
  1006. case SHAPE_RECT : f>>shape.rect ; break;
  1007. case SHAPE_BOX : f>>shape.box ; break;
  1008. case SHAPE_OBOX : f>>shape.obox ; break;
  1009. case SHAPE_CIRCLE : f>>shape.circle ; break;
  1010. case SHAPE_BALL : f>>shape.ball ; break;
  1011. case SHAPE_CAPSULE: f>>shape.capsule; break;
  1012. case SHAPE_TUBE : f>>shape.tube ; break;
  1013. case SHAPE_TORUS : f>>shape.torus ; break;
  1014. case SHAPE_CONE : f>>shape.cone ; break;
  1015. case SHAPE_PYRAMID: f>>shape.pyramid; break;
  1016. case SHAPE_PLANE : f>>shape.plane ; break;
  1017. }
  1018. if(f.pos(pos+72) && f.ok())return true; // 72 is the old size of raw memory for the shape data
  1019. }break;
  1020. case PHYS_CONVEX:
  1021. case PHYS_MESH :
  1022. {
  1023. PhysMesh pm; pm._type=_type;
  1024. if(pm._physx_cooked_data._loadRaw(f))
  1025. if(f.ok())
  1026. {
  1027. Loaded(pm);
  1028. pm.setBox();
  1029. Set(pm, T._pm);
  1030. return true;
  1031. }
  1032. }break;
  1033. }
  1034. }break;
  1035. }
  1036. error:
  1037. del(); return false;
  1038. }
  1039. Bool PhysPart::save(File &f)C
  1040. {
  1041. f.putUInt(CC4_PHSP);
  1042. return saveData(f);
  1043. }
  1044. Bool PhysPart::load(File &f)
  1045. {
  1046. switch(f.getUInt())
  1047. {
  1048. case CC4_PHSB: // compatibility reasons (this was used in the past)
  1049. case CC4_PHSP: return loadData(f);
  1050. case CC4_PHYS:
  1051. {
  1052. PhysBody phys; if(phys.loadData(f))
  1053. {
  1054. if(phys.parts.elms())Swap(T, phys.parts[0]);else del();
  1055. return true;
  1056. }
  1057. }break;
  1058. }
  1059. del(); return false;
  1060. }
  1061. Bool PhysPart::save(C Str &name)C
  1062. {
  1063. File f; if(f.writeTry(name)){if(save(f) && f.flush())return true; f.del(); FDelFile(name);}
  1064. return false;
  1065. }
  1066. Bool PhysPart::load(C Str &name)
  1067. {
  1068. File f; if(f.readTry(name))return load(f);
  1069. del(); return false;
  1070. }
  1071. /******************************************************************************/
  1072. // PHYSICAL BODY
  1073. /******************************************************************************/
  1074. void PhysBody::zero() {density=1; box.zero(); material=null;}
  1075. PhysBody::PhysBody() {zero();}
  1076. PhysBody& PhysBody::del()
  1077. {
  1078. parts.del(); zero();
  1079. return T;
  1080. }
  1081. /******************************************************************************/
  1082. Flt PhysBody::area ()C {Flt area =0; REPA(T)area +=parts[i].area (); return area ;}
  1083. Flt PhysBody::volume ()C {Flt volume=0; REPA(T)volume+=parts[i].volume(); return volume;}
  1084. Flt PhysBody::mass ()C {Flt mass =0; REPA(T)mass +=parts[i].mass (); return mass*finalDensity();}
  1085. Flt PhysBody::finalDensity()C {return material ? material->density()*density : density;}
  1086. Bool PhysBody::setBox ()
  1087. {
  1088. Bool found=false;
  1089. Box temp;
  1090. REPA(T)if(parts[i].getBox(temp))
  1091. {
  1092. if(!found){found=true; box=temp;}else box|=temp;
  1093. }
  1094. if(!found)box.zero(); return found;
  1095. }
  1096. /******************************************************************************/
  1097. PhysBody& PhysBody::transform(C Matrix3 &matrix) {REPAO(parts)*=matrix ; setBox(); return T;}
  1098. PhysBody& PhysBody::transform(C Matrix &matrix) {REPAO(parts)*=matrix ; setBox(); return T;}
  1099. PhysBody& PhysBody::mirrorX ( ) {REPAO(parts).mirrorX(); setBox(); return T;}
  1100. PhysBody& PhysBody::mirrorY ( ) {REPAO(parts).mirrorY(); setBox(); return T;}
  1101. PhysBody& PhysBody::mirrorZ ( ) {REPAO(parts).mirrorZ(); setBox(); return T;}
  1102. /******************************************************************************/
  1103. Bool PhysBody::adjustStorage(Bool universal, Bool physx, Bool bullet, Bool *changed)
  1104. {
  1105. if(changed)*changed=false;
  1106. Bool ok=true, c; REPA(T){ok&=parts[i].adjustStorage(universal, physx, bullet, &c); if(changed)*changed|=c;}
  1107. return ok;
  1108. }
  1109. PhysBody& PhysBody::freeHelperData() {REPAO(parts).freeHelperData(); return T;}
  1110. /******************************************************************************/
  1111. void PhysBody::draw(C Color &color)C
  1112. {
  1113. REPAO(parts).draw(color);
  1114. }
  1115. /******************************************************************************/
  1116. Bool PhysBody::saveData(File &f, CChar *path)C
  1117. {
  1118. f.putMulti(Byte(1), density, box); // version
  1119. f._putStr(PhysMtrls.name(material, path));
  1120. f.cmpUIntV(parts.elms()); FREPA(T)if(!parts[i].saveData(f))return false;
  1121. return f.ok();
  1122. }
  1123. Bool PhysBody::loadData(File &f, CChar *path)
  1124. {
  1125. switch(f.decUIntV())
  1126. {
  1127. case 1:
  1128. {
  1129. f.getMulti(density, box);
  1130. material=PhysMtrls(f._getStr(), path);
  1131. parts.setNum(f.decUIntV()); FREPA(T)if(!parts[i].loadData(f))return false;
  1132. if(f.ok())return true;
  1133. }break;
  1134. case 0:
  1135. {
  1136. f.skip(1); // old version byte
  1137. parts.setNum(f.getInt());
  1138. f.skip(1); // flag
  1139. f>>density;
  1140. material=null;
  1141. FREPA(T)if(!parts[i].loadData(f))return false;
  1142. setBox(); // set after loading all data
  1143. if(f.ok())return true;
  1144. }break;
  1145. }
  1146. del(); return false;
  1147. }
  1148. Bool PhysBody::save(File &f, CChar *path)C
  1149. {
  1150. f.putUInt(CC4_PHYS);
  1151. return saveData(f, path);
  1152. }
  1153. Bool PhysBody::load(File &f, CChar *path)
  1154. {
  1155. switch(f.getUInt())
  1156. {
  1157. case CC4_PHYS: return loadData(f, path);
  1158. case CC4_PHSB: // compatibility reasons (this was used in the past)
  1159. case CC4_PHSP:
  1160. {
  1161. if(del().parts.New().loadData(f)){setBox(); return true;}
  1162. }break;
  1163. }
  1164. del(); return false;
  1165. }
  1166. Bool PhysBody::save(C Str &name)C
  1167. {
  1168. File f; if(f.writeTry(name)){if(save(f, _GetPath(name)) && f.flush())return true; f.del(); FDelFile(name);}
  1169. return false;
  1170. }
  1171. Bool PhysBody::load(C Str &name)
  1172. {
  1173. File f; if(f.readTry(name))return load(f, _GetPath(name));
  1174. del(); return false;
  1175. }
  1176. /******************************************************************************/
  1177. Bool PhysBody::loadAdd(File &f, CChar *path)
  1178. {
  1179. if(!parts.elms())return load(f, path);
  1180. PhysBody phys;
  1181. if(phys.load(f, path))
  1182. {
  1183. if(phys.parts.elms())
  1184. {
  1185. density=Avg(density, phys.density);
  1186. box |=phys.box;
  1187. Int start=parts.addNum(phys.parts.elms());
  1188. FREPA(phys)Swap(parts[start+i], phys.parts[i]);
  1189. }
  1190. return true;
  1191. }
  1192. return false;
  1193. }
  1194. /******************************************************************************/
  1195. void PhysPart ::operator=(C Str &name) {if(!load(name))Exit(S+"Can't load Physical Body \""+name+"\"");}
  1196. void PhysBody ::operator=(C Str &name) {if(!load(name))Exit(S+"Can't load Physical Body \""+name+"\"");}
  1197. /******************************************************************************/
  1198. // PHYSICAL BODY GROUP
  1199. /******************************************************************************
  1200. struct PhysGroup // Physical Body Group (array of PhysBodies)
  1201. {
  1202. Mems<PhysBody> bodies; // physical bodies
  1203. // manage
  1204. PhysGroup& del ( ); // delete
  1205. PhysGroup& create(MeshLod &mshl); // create from MeshLod
  1206. PhysGroup& create(MeshGroup &mshg); // create from MeshGroup
  1207. // io
  1208. void operator=(C Str &name) ; // load, Exit on fail
  1209. Bool save (C Str &name)C; // save, false on fail
  1210. Bool load (C Str &name) ; // load, false on fail
  1211. Bool save ( File &f )C; // save, false on fail
  1212. Bool load ( File &f ) ; // load, false on fail
  1213. #if EE_PRIVATE
  1214. Bool saveData(File &f)C; // save, false on fail
  1215. Bool loadData(File &f) ; // load, false on fail
  1216. #endif
  1217. };
  1218. inline Int Elms(C PhysGroup &phsg) {return phsg.bodies.elms();}
  1219. /******************************************************************************
  1220. PhysGroup& PhysGroup::del()
  1221. {
  1222. bodies.del(); return T;
  1223. }
  1224. /******************************************************************************
  1225. PhysGroup& PhysGroup::create(MeshLod &mshl)
  1226. {
  1227. del();
  1228. MeshBase mesh; mesh.createPhys(mshl);
  1229. if(mesh.is())
  1230. {
  1231. PhysBody &phys=bodies.New();
  1232. phys.density=0;
  1233. phys.parts.New().createMesh(mesh);
  1234. phys.setBox();
  1235. }
  1236. return T;
  1237. }
  1238. PhysGroup& PhysGroup::create(MeshGroup &mshg)
  1239. {
  1240. del();
  1241. MeshBase mesh;
  1242. FREPA(mshg)
  1243. {
  1244. mesh.createPhys(mshg.meshes[i]);
  1245. if(mesh.is())
  1246. {
  1247. PhysBody &phys=bodies.New();
  1248. //phys.flag =0;
  1249. phys.density=0;
  1250. phys.parts.New().createMesh(mesh);
  1251. phys.setBox();
  1252. }
  1253. }
  1254. return T;
  1255. }
  1256. /******************************************************************************
  1257. Bool PhysGroup::saveData(File &f)C
  1258. {
  1259. f.cmpUIntV(0); // version
  1260. f.cmpUIntV(bodies.elms()); FREPA(T)if(!bodies[i].saveData(f))return false;
  1261. return f.ok();
  1262. }
  1263. Bool PhysGroup::loadData(File &f)
  1264. {
  1265. switch(f.decUIntV()) // version
  1266. {
  1267. case 0:
  1268. {
  1269. bodies.setNum(f.decUIntV()); FREPA(T)if(!bodies[i].loadData(f))return false;
  1270. if(f.ok())return true;
  1271. }break;
  1272. }
  1273. del(); return false;
  1274. }
  1275. Bool PhysGroup::save(File &f)C
  1276. {
  1277. f.putUInt(CC4_PHSG);
  1278. return saveData(f);
  1279. }
  1280. Bool PhysGroup::load(File &f)
  1281. {
  1282. switch(f.getUInt())
  1283. {
  1284. case CC4_PHSG: return loadData(f);
  1285. }
  1286. del(); return false;
  1287. }
  1288. Bool PhysGroup::save(C Str &name)C
  1289. {
  1290. File f; if(f.writeTry(name)){if(save(f) && f.flush())return true; f.del(); FDelFile(name);}
  1291. return false;
  1292. }
  1293. Bool PhysGroup::load(C Str &name)
  1294. {
  1295. File f; if(f.readTry(name))return load(f);
  1296. del(); return false;
  1297. }
  1298. void PhysGroup::operator=(C Str &name) {if(!load(name))Exit(S+"Can't load Physical Body \""+name+"\"");}
  1299. /******************************************************************************/
  1300. }
  1301. /******************************************************************************/