Physics Test.cpp 74 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. #if !PHYSX // Bullet
  4. #define CONVEX_RAY_TEST_SUB_SIMPLEX 0 // precision: low , performance: fastest
  5. #define CONVEX_RAY_TEST_GJK 1 // precision: high, performance: medium
  6. #define CONVEX_RAY_TEST_CCC 2 // precision: high, performance: slowest
  7. #define CONVEX_RAY_TEST CONVEX_RAY_TEST_GJK
  8. #include "../../../ThirdPartyLibs/begin.h"
  9. #include "../../../ThirdPartyLibs/Bullet/lib/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h"
  10. #if CONVEX_RAY_TEST==CONVEX_RAY_TEST_SUB_SIMPLEX
  11. #include "../../../ThirdPartyLibs/Bullet/lib/src/BulletCollision/NarrowPhaseCollision/btSubsimplexConvexCast.h"
  12. #elif CONVEX_RAY_TEST==CONVEX_RAY_TEST_GJK
  13. #include "../../../ThirdPartyLibs/Bullet/lib/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h"
  14. #elif CONVEX_RAY_TEST==CONVEX_RAY_TEST_CCC
  15. #include "../../../ThirdPartyLibs/Bullet/lib/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h"
  16. #include "../../../ThirdPartyLibs/Bullet/lib/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
  17. #endif
  18. #include "../../../ThirdPartyLibs/end.h"
  19. #endif
  20. namespace EE{
  21. /******************************************************************************
  22. PxTransform * operator uses reverse order:
  23. Matrix A, B;
  24. PxTransform a, b; A*B == b*a
  25. /******************************************************************************/
  26. Bool PhysPart::ray(C Vec &pos, C Vec &move, C Matrix *body_matrix, PhysHitBasic *phys_hit, Bool two_sided)C
  27. {
  28. if(type()==PHYS_SHAPE)
  29. {
  30. Vec p=pos, m=move;
  31. if(body_matrix)
  32. {
  33. p.div(*body_matrix );
  34. m.div( body_matrix->orn());
  35. }
  36. Flt frac; Vec normal;
  37. if(SweepPointShape(p, m, shape, phys_hit ? &frac : null, phys_hit ? &normal : null))
  38. {
  39. if(phys_hit)
  40. {
  41. if(body_matrix){normal*=body_matrix->orn(); normal.normalize();}
  42. phys_hit->face =-1;
  43. phys_hit->frac =frac;
  44. phys_hit->dist = frac*move.length();
  45. phys_hit->plane.pos =pos+frac*move;
  46. phys_hit->plane.normal=phys_hit->face_nrm=normal;
  47. }
  48. return true;
  49. }
  50. }else
  51. if(_pm)
  52. {
  53. #if PHYSX
  54. #if PHYSX_DLL_ACTUAL
  55. #define PxRaycast (decltype(&PxGeometryQuery::raycast)(Physx.raycast))
  56. if(!PxRaycast)Exit("PhysPart.ray\nPhysics hasn't been created");
  57. #else
  58. #define PxRaycast PxGeometryQuery::raycast
  59. #endif
  60. Vec dir=move; Flt length=dir.normalize();
  61. PxTransform transform=Physx.matrix(body_matrix ? *body_matrix : MatrixIdentity);
  62. Vec scale = (body_matrix ? body_matrix->scale() : Vec(1));
  63. PxVec3 px_pos =Physx.vec(pos),
  64. px_dir =Physx.vec(dir);
  65. PxMeshScale mesh_scale(Physx.vec(scale), PxQuat(PxIdentity));
  66. PxGeometryHolder geom;
  67. switch(_pm->_type)
  68. {
  69. case PHYS_MESH : geom.storeAny(PxTriangleMeshGeometry(_pm->_mesh , mesh_scale)); break;
  70. case PHYS_CONVEX: geom.storeAny( PxConvexMeshGeometry(_pm->_convex, mesh_scale)); break;
  71. }
  72. PxRaycastHit hits[1];
  73. PxHitFlag::Enum flag=(two_sided ? PxHitFlag::eMESH_BOTH_SIDES : PxHitFlag::Enum(0));
  74. if(phys_hit)
  75. {
  76. if(PxRaycast(px_pos, px_dir, geom.any(), transform, length, PxHitFlag::ePOSITION | PxHitFlag::eNORMAL | PxHitFlag::eDISTANCE | PxHitFlag::eFACE_INDEX | flag, Elms(hits), hits)>0)
  77. {
  78. phys_hit->set(hits[0], length);
  79. if(phys_hit->face>=0 && _pm->_type==PHYS_MESH)
  80. {
  81. Matrix3 orn; if(body_matrix) // normalize
  82. {
  83. orn.x=body_matrix->x/scale.x;
  84. orn.y=body_matrix->y/scale.y;
  85. orn.z=body_matrix->z/scale.z;
  86. }
  87. phys_hit->updateFace(geom.triangleMesh(), body_matrix ? &orn : null);
  88. }
  89. return true;
  90. }
  91. }else return PxRaycast(px_pos, px_dir, geom.any(), transform, length, PxHitFlag::eMESH_ANY | flag, Elms(hits), hits)>0; // if we don't pass 'hits' then this function won't do anything
  92. #else
  93. switch(_pm->_type)
  94. {
  95. case PHYS_CONVEX:
  96. {
  97. // code taken from "btCollisionWorld::rayTestSingleInternal"
  98. btSphereShape pointShape(0); pointShape.setMargin(0);
  99. btVoronoiSimplexSolver simplexSolver;
  100. #if CONVEX_RAY_TEST==CONVEX_RAY_TEST_SUB_SIMPLEX
  101. btSubsimplexConvexCast caster(&pointShape, _pm->_convex, &simplexSolver);
  102. #elif CONVEX_RAY_TEST==CONVEX_RAY_TEST_GJK
  103. btGjkConvexCast caster(&pointShape, _pm->_convex, &simplexSolver);
  104. #elif CONVEX_RAY_TEST==CONVEX_RAY_TEST_CCC
  105. btGjkEpaPenetrationDepthSolver gjkEpaPenetrationSolver; btContinuousConvexCollision caster(&pointShape, _pm->_convex, &simplexSolver, &gjkEpaPenetrationSolver);
  106. #endif
  107. btTransform rayFromTrans; rayFromTrans.setIdentity(); rayFromTrans.setOrigin(Bullet.vec(pos));
  108. btTransform rayToTrans ; rayToTrans .setIdentity(); rayToTrans .setOrigin(Bullet.vec(pos+move));
  109. btTransform colObjWorldTransform; if(body_matrix)colObjWorldTransform=Bullet.matrix(*body_matrix);else colObjWorldTransform.setIdentity();
  110. btConvexCast::CastResult castResult;
  111. if(caster.calcTimeOfImpact(rayFromTrans, rayToTrans, colObjWorldTransform, colObjWorldTransform, castResult))
  112. {
  113. if(phys_hit)
  114. {
  115. phys_hit->face=-1;
  116. phys_hit->frac=castResult.m_fraction;
  117. phys_hit->dist=phys_hit->frac*move.length();
  118. phys_hit->face_nrm=Bullet.vec(castResult.m_normal);
  119. phys_hit->plane.set(Bullet.vec(castResult.m_hitPoint), phys_hit->face_nrm);
  120. }
  121. return true;
  122. }
  123. }break;
  124. case PHYS_MESH:
  125. {
  126. Vec p=pos, m=move;
  127. if(body_matrix)
  128. {
  129. p.div(*body_matrix );
  130. m.div( body_matrix->orn());
  131. }
  132. struct Callback : btTriangleRaycastCallback
  133. {
  134. PhysHitBasic *phys_hit;
  135. Bool hit;
  136. virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex)
  137. {
  138. hit=true;
  139. if(phys_hit)
  140. {
  141. phys_hit->face =triangleIndex;
  142. phys_hit->frac =hitFraction;
  143. phys_hit->face_nrm=Bullet.vec(hitNormalLocal);
  144. }
  145. return hitFraction;
  146. }
  147. Callback(const btVector3& from, const btVector3& to, unsigned int flags, PhysHitBasic *phys_hit) : btTriangleRaycastCallback(from, to, flags), phys_hit(phys_hit), hit(false) {}
  148. };
  149. Callback callback(Bullet.vec(p), Bullet.vec(p+m), btTriangleRaycastCallback::kF_KeepUnflippedNormal | (two_sided ? 0 : btTriangleRaycastCallback::kF_FilterBackfaces), phys_hit);
  150. _pm->_mesh->performRaycast(&callback, callback.m_from, callback.m_to);
  151. if(callback.hit && phys_hit)
  152. {
  153. if(body_matrix)phys_hit->face_nrm.mul(body_matrix->orn()).normalize();
  154. phys_hit->dist=phys_hit->frac*move.length();
  155. phys_hit->plane.set(pos+move*phys_hit->frac, phys_hit->face_nrm);
  156. }
  157. return callback.hit;
  158. }break;
  159. }
  160. #endif
  161. }
  162. return false;
  163. }
  164. /******************************************************************************/
  165. #if PHYSX
  166. /******************************************************************************/
  167. #define INITIAL_OVERLAP_ON PxHitFlags()
  168. #define INITIAL_OVERLAP_OFF PxHitFlag::eASSUME_NO_INITIAL_OVERLAP
  169. #define INITIAL_OVERLAP INITIAL_OVERLAP_OFF // this is used only for sweeps
  170. void ActorInfo::set(PxShape *shape)
  171. {
  172. if(T._actor=(shape ? shape->getActor() : null))
  173. {
  174. PxRigidDynamic *rigid_dynamic=_actor->is<PxRigidDynamic>();
  175. collision= FlagTest((UInt) shape->getFlags (), PxShapeFlag::eSIMULATION_SHAPE) ;
  176. dynamic =(rigid_dynamic && !FlagTest((UInt)rigid_dynamic->getRigidBodyFlags(), PxRigidBodyFlag::eKINEMATIC ));
  177. group = shape->getSimulationFilterData().word0;
  178. user = _actor->userData;
  179. obj =(Ptr)_actor->getName();
  180. }else
  181. {
  182. collision=false;
  183. dynamic =false;
  184. group =0;
  185. user =null;
  186. obj =null;
  187. }
  188. }
  189. /******************************************************************************/
  190. void PhysHitBasic::set(C PxLocationHit &hit, Flt move_length)
  191. {
  192. face=hit.faceIndex;
  193. dist=hit.distance;
  194. frac=(move_length ? dist/move_length : 0);
  195. plane.pos =Physx.vec(hit.position);
  196. face_nrm=plane.normal=Physx.vec(hit.normal );
  197. }
  198. void PhysHitBasic::updateFace(C PxTriangleMeshGeometry &mesh, C Matrix3 *orn)
  199. {
  200. if(mesh.triangleMesh && InRange(face, mesh.triangleMesh->getNbTriangles()))
  201. {
  202. C Vec *pos =(Vec*)mesh.triangleMesh->getVertices();
  203. Vec scale=Physx.vec(mesh.scale.scale);
  204. VecI ind;
  205. if(mesh.triangleMesh->getTriangleMeshFlags()&PxTriangleMeshFlag::e16_BIT_INDICES)ind=((VecUS*)mesh.triangleMesh->getTriangles())[face];
  206. else ind=((VecI *)mesh.triangleMesh->getTriangles())[face];
  207. face_nrm =GetNormal(pos[ind.x]*scale, pos[ind.y]*scale, pos[ind.z]*scale);
  208. if(orn)face_nrm*=*orn;
  209. if(C PxU32 *remap=mesh.triangleMesh->getTrianglesRemap())face=remap[face]; // remap to original index if available, do this at the end because other operations operate on phys mesh index
  210. }
  211. }
  212. void PhysHit::set(C PxLocationHit &hit, Flt move_length)
  213. {
  214. ActorInfo::set(hit.shape); // set this first, because we need to set '_actor'
  215. PhysHitBasic::set(hit, move_length);
  216. if(face>=0 && _actor /*&& hit.shape*/ && hit.shape->getGeometryType()==PxGeometryType::eTRIANGLEMESH) // no need to check for 'hit.shape' because we already check for '_actor' and it will be set only if shape is
  217. {
  218. PxTriangleMeshGeometry mesh;
  219. if(hit.shape->getTriangleMeshGeometry(mesh))updateFace(mesh, &Physx.orn(_actor->getGlobalPose().q));
  220. }
  221. }
  222. /******************************************************************************/
  223. // CUTS
  224. /******************************************************************************
  225. struct CutsCallback : PxQueryFilterCallback
  226. {
  227. virtual PxQueryHitType::Enum preFilter(const PxFilterData &filterData, PxShape* shape, PxQueryFlags &filterFlags)
  228. {
  229. return ? PxQueryHitType::eTOUCH : PxQueryHitType::eNONE;
  230. }
  231. virtual PxQueryHitType::Enum postFilter(const PxFilterData &filterData, const PxQueryHit &hit)
  232. {
  233. return PxQueryHitType::eTOUCH;
  234. }
  235. };
  236. /******************************************************************************/
  237. Bool PhysicsClass::cuts(C Box &box, UInt groups)
  238. {
  239. if(Physx.world && groups)
  240. {
  241. PxOverlapBuffer buf;
  242. PxQueryFilterData qfd(PxQueryFlag::eDYNAMIC | PxQueryFlag::eSTATIC | PxQueryFlag::eANY_HIT | PxQueryFlag::eNO_BLOCK); qfd.data.word0=groups;
  243. ReadLock lock(Physics._rws);
  244. return Physx.world->overlap(PxBoxGeometry(box.w()*0.5f, box.h()*0.5f, box.d()*0.5f), Physx.matrix(box.center()), buf, qfd);
  245. }
  246. return false;
  247. }
  248. /******************************************************************************/
  249. Bool PhysicsClass::cuts(C OBox &obox, UInt groups)
  250. {
  251. if(Physx.world && groups)
  252. {
  253. PxOverlapBuffer buf;
  254. PxQueryFilterData qfd(PxQueryFlag::eDYNAMIC | PxQueryFlag::eSTATIC | PxQueryFlag::eANY_HIT | PxQueryFlag::eNO_BLOCK); qfd.data.word0=groups;
  255. ReadLock lock(Physics._rws);
  256. return Physx.world->overlap(PxBoxGeometry(obox.box.w()*0.5f, obox.box.h()*0.5f, obox.box.d()*0.5f), Physx.matrix(Matrix(obox.center(), obox.matrix.orn())), buf, qfd);
  257. }
  258. return false;
  259. }
  260. /******************************************************************************/
  261. Bool PhysicsClass::cuts(C Ball &ball, UInt groups)
  262. {
  263. if(Physx.world && groups)
  264. {
  265. PxOverlapBuffer buf;
  266. PxQueryFilterData qfd(PxQueryFlag::eDYNAMIC | PxQueryFlag::eSTATIC | PxQueryFlag::eANY_HIT | PxQueryFlag::eNO_BLOCK); qfd.data.word0=groups;
  267. ReadLock lock(Physics._rws);
  268. return Physx.world->overlap(PxSphereGeometry(ball.r), Physx.matrix(ball.pos), buf, qfd);
  269. }
  270. return false;
  271. }
  272. /******************************************************************************/
  273. Bool PhysicsClass::cuts(C Capsule &capsule, UInt groups)
  274. {
  275. if(Physx.world && groups)
  276. {
  277. PxOverlapBuffer buf;
  278. PxQueryFilterData qfd(PxQueryFlag::eDYNAMIC | PxQueryFlag::eSTATIC | PxQueryFlag::eANY_HIT | PxQueryFlag::eNO_BLOCK); qfd.data.word0=groups;
  279. ReadLock lock(Physics._rws);
  280. return Physx.world->overlap(PxCapsuleGeometry(capsule.r, capsule.h*0.5f-capsule.r), Physx.matrix(Matrix().setPosRight(capsule.pos, capsule.up)), buf, qfd);
  281. }
  282. return false;
  283. }
  284. /******************************************************************************/
  285. // CUTS CALLBACK
  286. /******************************************************************************/
  287. struct CutsCallbackAll : PxQueryFilterCallback
  288. {
  289. PhysCutsCallback *callback;
  290. Memt<C PxRigidActor*> actors;
  291. CutsCallbackAll(PhysCutsCallback &callback) : callback(&callback) {}
  292. virtual PxQueryHitType::Enum preFilter(const PxFilterData &filterData, const PxShape *shape, const PxRigidActor *actor, PxHitFlags &filterFlags)
  293. {
  294. return (callback && !actors.has(actor)) ? PxQueryHitType::eTOUCH : PxQueryHitType::eNONE;
  295. }
  296. virtual PxQueryHitType::Enum postFilter(const PxFilterData &filterData, const PxQueryHit &hit)
  297. {
  298. if(callback && hit.shape)
  299. if(PxRigidActor *actor=hit.shape->getActor())
  300. if(actors.include(actor))
  301. {
  302. ActorInfo actor; actor.set(hit.shape); if(!callback->hit(actor))callback=null;
  303. }
  304. return PxQueryHitType::eNONE; // return NONE so it won't need to be stored in the output buffer (which we don't specify)
  305. }
  306. };
  307. /******************************************************************************/
  308. void PhysicsClass::cuts(C Box &box, PhysCutsCallback &callback, UInt groups)
  309. {
  310. if(Physx.world && groups)
  311. {
  312. PxOverlapBuffer buf;
  313. PxQueryFilterData qfd(PxQueryFlag::eDYNAMIC | PxQueryFlag::eSTATIC | PxQueryFlag::ePREFILTER | PxQueryFlag::ePOSTFILTER | PxQueryFlag::eNO_BLOCK); qfd.data.word0=groups;
  314. ReadLock lock(Physics._rws);
  315. Physx.world->overlap(PxBoxGeometry(box.w()*0.5f, box.h()*0.5f, box.d()*0.5f), Physx.matrix(box.center()), buf, qfd, &CutsCallbackAll(callback));
  316. }
  317. }
  318. /******************************************************************************/
  319. void PhysicsClass::cuts(C OBox &obox, PhysCutsCallback &callback, UInt groups)
  320. {
  321. if(Physx.world && groups)
  322. {
  323. PxOverlapBuffer buf;
  324. PxQueryFilterData qfd(PxQueryFlag::eDYNAMIC | PxQueryFlag::eSTATIC | PxQueryFlag::ePREFILTER | PxQueryFlag::ePOSTFILTER | PxQueryFlag::eNO_BLOCK); qfd.data.word0=groups;
  325. ReadLock lock(Physics._rws);
  326. Physx.world->overlap(PxBoxGeometry(obox.box.w()*0.5f, obox.box.h()*0.5f, obox.box.d()*0.5f), Physx.matrix(Matrix(obox.center(), obox.matrix.orn())), buf, qfd, &CutsCallbackAll(callback));
  327. }
  328. }
  329. /******************************************************************************/
  330. void PhysicsClass::cuts(C Ball &ball, PhysCutsCallback &callback, UInt groups)
  331. {
  332. if(Physx.world && groups)
  333. {
  334. PxOverlapBuffer buf;
  335. PxQueryFilterData qfd(PxQueryFlag::eDYNAMIC | PxQueryFlag::eSTATIC | PxQueryFlag::ePREFILTER | PxQueryFlag::ePOSTFILTER | PxQueryFlag::eNO_BLOCK); qfd.data.word0=groups;
  336. ReadLock lock(Physics._rws);
  337. Physx.world->overlap(PxSphereGeometry(ball.r), Physx.matrix(ball.pos), buf, qfd, &CutsCallbackAll(callback));
  338. }
  339. }
  340. /******************************************************************************/
  341. void PhysicsClass::cuts(C Capsule &capsule, PhysCutsCallback &callback, UInt groups)
  342. {
  343. if(Physx.world && groups)
  344. {
  345. PxOverlapBuffer buf;
  346. PxQueryFilterData qfd(PxQueryFlag::eDYNAMIC | PxQueryFlag::eSTATIC | PxQueryFlag::ePREFILTER | PxQueryFlag::ePOSTFILTER | PxQueryFlag::eNO_BLOCK); qfd.data.word0=groups;
  347. ReadLock lock(Physics._rws);
  348. Physx.world->overlap(PxCapsuleGeometry(capsule.r, capsule.h*0.5f-capsule.r), Physx.matrix(Matrix().setPosRight(capsule.pos, capsule.up)), buf, qfd, &CutsCallbackAll(callback));
  349. }
  350. }
  351. /******************************************************************************/
  352. // ACTOR CUTS
  353. /******************************************************************************/
  354. Bool Actor::cuts(UInt groups)C
  355. {
  356. struct ActorCutsCallback : PxQueryFilterCallback
  357. {
  358. C PxRigidActor *actor;
  359. ActorCutsCallback(C PxRigidActor *actor) {T.actor=actor;}
  360. virtual PxQueryHitType::Enum preFilter(const PxFilterData &filterData, const PxShape *shape, const PxRigidActor *actor, PxHitFlags &queryFlags)
  361. {
  362. return (actor!=T.actor) ? PxQueryHitType::eTOUCH : PxQueryHitType::eNONE;
  363. }
  364. virtual PxQueryHitType::Enum postFilter(const PxFilterData &filterData, const PxQueryHit &hit) // this isn't used but must be defined due to abstract class
  365. {
  366. return PxQueryHitType::eTOUCH;
  367. }
  368. };
  369. if(_actor && Physx.world && groups)
  370. {
  371. ActorCutsCallback acc(_actor); PxShape *shape;
  372. PxOverlapBuffer buf;
  373. PxQueryFilterData qfd(PxQueryFlag::eDYNAMIC | PxQueryFlag::eSTATIC | PxQueryFlag::ePREFILTER | PxQueryFlag::eANY_HIT | PxQueryFlag::eNO_BLOCK); qfd.data.word0=groups;
  374. ReadLock lock(Physics._rws);
  375. REP(_actor->getNbShapes())if(_actor->getShapes(&shape, 1, i))switch(shape->getGeometryType())
  376. {
  377. case PxGeometryType::eBOX : {PxBoxGeometry box ; if(shape->getBoxGeometry (box ))if(Physx.world->overlap(box , _actor->getGlobalPose()*shape->getLocalPose(), buf, qfd, &acc))return true;} break;
  378. case PxGeometryType::eSPHERE : {PxSphereGeometry sphere ; if(shape->getSphereGeometry (sphere ))if(Physx.world->overlap(sphere , _actor->getGlobalPose()*shape->getLocalPose(), buf, qfd, &acc))return true;} break;
  379. case PxGeometryType::eCAPSULE : {PxCapsuleGeometry capsule; if(shape->getCapsuleGeometry (capsule))if(Physx.world->overlap(capsule, _actor->getGlobalPose()*shape->getLocalPose(), buf, qfd, &acc))return true;} break;
  380. case PxGeometryType::eCONVEXMESH: {PxConvexMeshGeometry convex ; if(shape->getConvexMeshGeometry(convex ))if(Physx.world->overlap(convex , _actor->getGlobalPose()*shape->getLocalPose(), buf, qfd, &acc))return true;} break;
  381. }
  382. }
  383. return false;
  384. }
  385. /******************************************************************************/
  386. void Actor::cuts(PhysCutsCallback &callback, UInt groups)C
  387. {
  388. struct ActorCutsCallbackAll : PxQueryFilterCallback
  389. {
  390. Memt<C PxRigidActor*> actors;
  391. PhysCutsCallback *callback;
  392. ActorCutsCallbackAll(PhysCutsCallback &callback, C PxRigidActor &actor) : callback(&callback) {T.actors.add(&actor);}
  393. virtual PxQueryHitType::Enum preFilter(const PxFilterData &filterData, const PxShape *shape, const PxRigidActor *actor, PxHitFlags &queryFlags)
  394. {
  395. return (callback && !actors.has(actor)) ? PxQueryHitType::eTOUCH : PxQueryHitType::eNONE;
  396. }
  397. virtual PxQueryHitType::Enum postFilter(const PxFilterData &filterData, const PxQueryHit &hit)
  398. {
  399. if(callback)
  400. if(PxRigidActor *actor=hit.shape->getActor())
  401. if(actors.include(actor))
  402. {
  403. ActorInfo actor; actor.set(hit.shape); if(!callback->hit(actor))callback=null;
  404. }
  405. return PxQueryHitType::eNONE; // return NONE so it won't need to be stored in the output buffer (which we don't specify)
  406. }
  407. };
  408. if(_actor && Physx.world && groups)
  409. {
  410. ActorCutsCallbackAll acc(callback, *_actor); PxShape *shape;
  411. PxOverlapBuffer buf;
  412. PxQueryFilterData qfd(PxQueryFlag::eDYNAMIC | PxQueryFlag::eSTATIC | PxQueryFlag::ePREFILTER | PxQueryFlag::ePOSTFILTER | PxQueryFlag::eNO_BLOCK); qfd.data.word0=groups;
  413. ReadLock lock(Physics._rws);
  414. REP(_actor->getNbShapes())if(_actor->getShapes(&shape, 1, i))switch(shape->getGeometryType())
  415. {
  416. case PxGeometryType::eBOX : {PxBoxGeometry box ; if(shape->getBoxGeometry (box ))Physx.world->overlap(box , _actor->getGlobalPose()*shape->getLocalPose(), buf, qfd, &acc);} break;
  417. case PxGeometryType::eSPHERE : {PxSphereGeometry sphere ; if(shape->getSphereGeometry (sphere ))Physx.world->overlap(sphere , _actor->getGlobalPose()*shape->getLocalPose(), buf, qfd, &acc);} break;
  418. case PxGeometryType::eCAPSULE : {PxCapsuleGeometry capsule; if(shape->getCapsuleGeometry (capsule))Physx.world->overlap(capsule, _actor->getGlobalPose()*shape->getLocalPose(), buf, qfd, &acc);} break;
  419. case PxGeometryType::eCONVEXMESH: {PxConvexMeshGeometry convex ; if(shape->getConvexMeshGeometry(convex ))Physx.world->overlap(convex , _actor->getGlobalPose()*shape->getLocalPose(), buf, qfd, &acc);} break;
  420. }
  421. }
  422. }
  423. /******************************************************************************/
  424. // RAY
  425. /******************************************************************************/
  426. Bool PhysicsClass::ray(C Vec &pos, C Vec &move, PhysHit *phys_hit, UInt groups)
  427. {
  428. /*struct RayCallback : PxQueryFilterCallback
  429. {
  430. virtual PxQueryHitType::Enum preFilter(const PxFilterData &filterData, PxShape *shape, PxQueryFlags &filterFlags)
  431. {
  432. return ? PxQueryHitType::eBLOCK : PxQueryHitType::eNONE;
  433. }
  434. virtual PxQueryHitType::Enum postFilter(const PxFilterData &filterData, const PxQueryHit &hit)
  435. {
  436. return PxQueryHitType::eBLOCK;
  437. }
  438. };*/
  439. if(Physx.world && groups)
  440. {
  441. Vec dir =move;
  442. Flt length=dir.normalize();
  443. PxRaycastBuffer buf;
  444. PxQueryFilterData qfd(PxQueryFlag::eDYNAMIC | PxQueryFlag::eSTATIC); qfd.data.word0=groups;
  445. ReadLock lock(Physics._rws);
  446. if(phys_hit)
  447. {
  448. if(Physx.world->raycast(Physx.vec(pos), Physx.vec(dir), length, buf, PxHitFlag::ePOSITION | PxHitFlag::eNORMAL | PxHitFlag::eDISTANCE | PxHitFlag::eFACE_INDEX, qfd))
  449. {
  450. phys_hit->set(buf.block, length); return true;
  451. }
  452. }else
  453. {
  454. qfd.flags|=PxQueryFlag::eANY_HIT;
  455. return Physx.world->raycast(Physx.vec(pos), Physx.vec(dir), length, buf, PxHitFlags(), qfd);
  456. }
  457. }
  458. return false;
  459. }
  460. void PhysicsClass::ray(C Vec &pos, C Vec &move, PhysHitCallback &callback, UInt groups)
  461. {
  462. struct RayCallbackAll : PxQueryFilterCallback
  463. {
  464. Flt move_length;
  465. PhysHitCallback *callback;
  466. RayCallbackAll(PhysHitCallback &callback, Flt move_length) : callback(&callback) {T.move_length=move_length;}
  467. virtual PxQueryHitType::Enum preFilter(const PxFilterData &filterData, const PxShape *shape, const PxRigidActor *actor, PxHitFlags &queryFlags)
  468. {
  469. return callback ? PxQueryHitType::eTOUCH : PxQueryHitType::eNONE;
  470. }
  471. virtual PxQueryHitType::Enum postFilter(const PxFilterData &filterData, const PxQueryHit &hit)
  472. {
  473. if(callback)
  474. {
  475. C PxRaycastHit &ray_hit=(C PxRaycastHit&)hit;
  476. PhysHit phys_hit; phys_hit.set(ray_hit, move_length); if(!callback->hit(phys_hit))callback=null;
  477. }
  478. return PxQueryHitType::eNONE; // return NONE so it won't need to be stored in the output buffer (which we don't specify)
  479. }
  480. };
  481. if(Physx.world && groups)
  482. {
  483. Vec dir =move;
  484. Flt length=dir.normalize();
  485. PxRaycastBuffer buf;
  486. PxQueryFilterData qfd(PxQueryFlag::eDYNAMIC | PxQueryFlag::eSTATIC | PxQueryFlag::ePREFILTER | PxQueryFlag::ePOSTFILTER); qfd.data.word0=groups;
  487. ReadLock lock(Physics._rws);
  488. Physx.world->raycast(Physx.vec(pos), Physx.vec(dir), length, buf, PxHitFlag::ePOSITION | PxHitFlag::eNORMAL | PxHitFlag::eDISTANCE | PxHitFlag::eFACE_INDEX | PxHitFlag::eMESH_MULTIPLE, qfd, &RayCallbackAll(callback, length));
  489. }
  490. }
  491. /******************************************************************************/
  492. // SWEEP
  493. /******************************************************************************
  494. struct SweepCallback : PxQueryFilterCallback
  495. {
  496. virtual PxQueryHitType::Enum preFilter(const PxFilterData &filterData, PxShape *shape, PxQueryFlags &filterFlags)
  497. {
  498. return ? PxQueryHitType::eTOUCH : PxQueryHitType::eNONE;
  499. }
  500. virtual PxQueryHitType::Enum postFilter(const PxFilterData &filterData, const PxQueryHit &hit)
  501. {
  502. return PxQueryHitType::eTOUCH;
  503. }
  504. };
  505. /******************************************************************************/
  506. Bool PhysicsClass::sweep(C Box &box, C Vec &move, PhysHit *phys_hit, UInt groups)
  507. {
  508. if(Physx.world && groups)
  509. {
  510. Vec dir=move; Flt length=dir.normalize(); PxBoxGeometry geom(box.w()*0.5f, box.h()*0.5f, box.d()*0.5f); PxTransform pose=Physx.matrix(box.center());
  511. PxSweepBuffer buf;
  512. PxQueryFilterData qfd(PxQueryFlag::eDYNAMIC | PxQueryFlag::eSTATIC); qfd.data.word0=groups;
  513. ReadLock lock(Physics._rws);
  514. if(phys_hit)
  515. {
  516. if(Physx.world->sweep(geom, pose, Physx.vec(dir), length, buf, PxHitFlag::ePOSITION | PxHitFlag::eNORMAL | PxHitFlag::eDISTANCE | PxHitFlag::eFACE_INDEX | PxHitFlag::ePRECISE_SWEEP | INITIAL_OVERLAP, qfd)){phys_hit->set(buf.block, length); return true;}
  517. }else
  518. {
  519. qfd.flags|=PxQueryFlag::eANY_HIT;
  520. return Physx.world->sweep(geom, pose, Physx.vec(dir), length, buf, PxHitFlag::ePRECISE_SWEEP | PxHitFlag::eMESH_ANY | INITIAL_OVERLAP, qfd);
  521. }
  522. }
  523. return false;
  524. }
  525. Bool PhysicsClass::sweep(C OBox &obox, C Vec &move, PhysHit *phys_hit, UInt groups)
  526. {
  527. if(Physx.world && groups)
  528. {
  529. Vec dir=move; Flt length=dir.normalize(); PxBoxGeometry geom(obox.box.w()*0.5f, obox.box.h()*0.5f, obox.box.d()*0.5f); PxTransform pose=Physx.matrix(Matrix(obox.center(), obox.matrix.orn()));
  530. PxSweepBuffer buf;
  531. PxQueryFilterData qfd(PxQueryFlag::eDYNAMIC | PxQueryFlag::eSTATIC); qfd.data.word0=groups;
  532. ReadLock lock(Physics._rws);
  533. if(phys_hit)
  534. {
  535. if(Physx.world->sweep(geom, pose, Physx.vec(dir), length, buf, PxHitFlag::ePOSITION | PxHitFlag::eNORMAL | PxHitFlag::eDISTANCE | PxHitFlag::eFACE_INDEX | PxHitFlag::ePRECISE_SWEEP | INITIAL_OVERLAP, qfd)){phys_hit->set(buf.block, length); return true;}
  536. }else
  537. {
  538. qfd.flags|=PxQueryFlag::eANY_HIT;
  539. return Physx.world->sweep(geom, pose, Physx.vec(dir), length, buf, PxHitFlag::ePRECISE_SWEEP | PxHitFlag::eMESH_ANY | INITIAL_OVERLAP, qfd);
  540. }
  541. }
  542. return false;
  543. }
  544. Bool PhysicsClass::sweep(C Ball &ball, C Vec &move, PhysHit *phys_hit, UInt groups)
  545. {
  546. if(Physx.world && groups)
  547. {
  548. Vec dir=move; Flt length=dir.normalize(); PxSphereGeometry geom(ball.r); PxTransform pose=Physx.matrix(ball.pos);
  549. PxSweepBuffer buf;
  550. PxQueryFilterData qfd(PxQueryFlag::eDYNAMIC | PxQueryFlag::eSTATIC); qfd.data.word0=groups;
  551. ReadLock lock(Physics._rws);
  552. if(phys_hit)
  553. {
  554. if(Physx.world->sweep(geom, pose, Physx.vec(dir), length, buf, PxHitFlag::ePOSITION | PxHitFlag::eNORMAL | PxHitFlag::eDISTANCE | PxHitFlag::eFACE_INDEX | PxHitFlag::ePRECISE_SWEEP | INITIAL_OVERLAP, qfd)){phys_hit->set(buf.block, length); return true;}
  555. }else
  556. {
  557. qfd.flags|=PxQueryFlag::eANY_HIT;
  558. return Physx.world->sweep(geom, pose, Physx.vec(dir), length, buf, PxHitFlag::ePRECISE_SWEEP | PxHitFlag::eMESH_ANY | INITIAL_OVERLAP, qfd);
  559. }
  560. }
  561. return false;
  562. }
  563. Bool PhysicsClass::sweep(C Capsule &capsule, C Vec &move, PhysHit *phys_hit, UInt groups)
  564. {
  565. if(Physx.world && groups)
  566. {
  567. Vec dir=move; Flt length=dir.normalize(); PxCapsuleGeometry geom(capsule.r, capsule.h*0.5f-capsule.r); PxTransform pose=Physx.matrix(Matrix().setPosRight(capsule.pos, capsule.up));
  568. PxSweepBuffer buf;
  569. PxQueryFilterData qfd(PxQueryFlag::eDYNAMIC | PxQueryFlag::eSTATIC); qfd.data.word0=groups;
  570. ReadLock lock(Physics._rws);
  571. if(phys_hit)
  572. {
  573. if(Physx.world->sweep(geom, pose, Physx.vec(dir), length, buf, PxHitFlag::ePOSITION | PxHitFlag::eNORMAL | PxHitFlag::eDISTANCE | PxHitFlag::eFACE_INDEX | PxHitFlag::ePRECISE_SWEEP | INITIAL_OVERLAP, qfd)){phys_hit->set(buf.block, length); return true;}
  574. }else
  575. {
  576. qfd.flags|=PxQueryFlag::eANY_HIT;
  577. return Physx.world->sweep(geom, pose, Physx.vec(dir), length, buf, PxHitFlag::ePRECISE_SWEEP | PxHitFlag::eMESH_ANY | INITIAL_OVERLAP, qfd);
  578. }
  579. }
  580. return false;
  581. }
  582. /******************************************************************************/
  583. // SWEEP CALLBACK
  584. /******************************************************************************/
  585. struct SweepCallbackAll : PxQueryFilterCallback
  586. {
  587. Flt move_length;
  588. PhysHitCallback *callback;
  589. SweepCallbackAll(PhysHitCallback &callback, Flt move_length) : callback(&callback) {T.move_length=move_length;}
  590. virtual PxQueryHitType::Enum preFilter(const PxFilterData &filterData, const PxShape *shape, const PxRigidActor *actor, PxHitFlags &queryFlags)
  591. {
  592. return callback ? PxQueryHitType::eTOUCH : PxQueryHitType::eNONE;
  593. }
  594. virtual PxQueryHitType::Enum postFilter(const PxFilterData &filterData, const PxQueryHit &hit)
  595. {
  596. if(callback)
  597. {
  598. C PxSweepHit &sweep_hit=(C PxSweepHit&)hit;
  599. PhysHit phys_hit; phys_hit.set(sweep_hit, move_length); if(!callback->hit(phys_hit))callback=null;
  600. }
  601. return PxQueryHitType::eNONE; // return NONE so it won't need to be stored in the output buffer (which we don't specify)
  602. }
  603. };
  604. /******************************************************************************/
  605. void PhysicsClass::sweep(C Box &box, C Vec &move, PhysHitCallback &callback, UInt groups)
  606. {
  607. if(Physx.world && groups)
  608. {
  609. Vec dir=move; Flt length=dir.normalize();
  610. PxSweepBuffer buf;
  611. PxQueryFilterData qfd(PxQueryFlag::eDYNAMIC | PxQueryFlag::eSTATIC | PxQueryFlag::ePREFILTER | PxQueryFlag::ePOSTFILTER); qfd.data.word0=groups;
  612. ReadLock lock(Physics._rws);
  613. Physx.world->sweep(PxBoxGeometry(box.w()*0.5f, box.h()*0.5f, box.d()*0.5f), Physx.matrix(box.center()), Physx.vec(dir), length, buf, PxHitFlag::ePOSITION | PxHitFlag::eNORMAL | PxHitFlag::eDISTANCE | PxHitFlag::eFACE_INDEX | PxHitFlag::ePRECISE_SWEEP | PxHitFlag::eMESH_MULTIPLE | INITIAL_OVERLAP, qfd, &SweepCallbackAll(callback, length));
  614. }
  615. }
  616. void PhysicsClass::sweep(C OBox &obox, C Vec &move, PhysHitCallback &callback, UInt groups)
  617. {
  618. if(Physx.world && groups)
  619. {
  620. Vec dir=move; Flt length=dir.normalize();
  621. PxSweepBuffer buf;
  622. PxQueryFilterData qfd(PxQueryFlag::eDYNAMIC | PxQueryFlag::eSTATIC | PxQueryFlag::ePREFILTER | PxQueryFlag::ePOSTFILTER); qfd.data.word0=groups;
  623. ReadLock lock(Physics._rws);
  624. Physx.world->sweep(PxBoxGeometry(obox.box.w()*0.5f, obox.box.h()*0.5f, obox.box.d()*0.5f), Physx.matrix(Matrix(obox.center(), obox.matrix.orn())), Physx.vec(dir), length, buf, PxHitFlag::ePOSITION | PxHitFlag::eNORMAL | PxHitFlag::eDISTANCE | PxHitFlag::eFACE_INDEX | PxHitFlag::ePRECISE_SWEEP | PxHitFlag::eMESH_MULTIPLE | INITIAL_OVERLAP, qfd, &SweepCallbackAll(callback, length));
  625. }
  626. }
  627. void PhysicsClass::sweep(C Ball &ball, C Vec &move, PhysHitCallback &callback, UInt groups)
  628. {
  629. if(Physx.world && groups)
  630. {
  631. Vec dir=move; Flt length=dir.normalize();
  632. PxSweepBuffer buf;
  633. PxQueryFilterData qfd(PxQueryFlag::eDYNAMIC | PxQueryFlag::eSTATIC | PxQueryFlag::ePREFILTER | PxQueryFlag::ePOSTFILTER); qfd.data.word0=groups;
  634. ReadLock lock(Physics._rws);
  635. Physx.world->sweep(PxSphereGeometry(ball.r), Physx.matrix(ball.pos), Physx.vec(dir), length, buf, PxHitFlag::ePOSITION | PxHitFlag::eNORMAL | PxHitFlag::eDISTANCE | PxHitFlag::eFACE_INDEX | PxHitFlag::ePRECISE_SWEEP | PxHitFlag::eMESH_MULTIPLE | INITIAL_OVERLAP, qfd, &SweepCallbackAll(callback, length));
  636. }
  637. }
  638. void PhysicsClass::sweep(C Capsule &capsule, C Vec &move, PhysHitCallback &callback, UInt groups)
  639. {
  640. if(Physx.world && groups)
  641. {
  642. Vec dir=move; Flt length=dir.normalize();
  643. PxSweepBuffer buf;
  644. PxQueryFilterData qfd(PxQueryFlag::eDYNAMIC | PxQueryFlag::eSTATIC | PxQueryFlag::ePREFILTER | PxQueryFlag::ePOSTFILTER); qfd.data.word0=groups;
  645. ReadLock lock(Physics._rws);
  646. Physx.world->sweep(PxCapsuleGeometry(capsule.r, capsule.h*0.5f-capsule.r), Physx.matrix(Matrix().setPosRight(capsule.pos, capsule.up)), Physx.vec(dir), length, buf, PxHitFlag::ePOSITION | PxHitFlag::eNORMAL | PxHitFlag::eDISTANCE | PxHitFlag::eFACE_INDEX | PxHitFlag::ePRECISE_SWEEP | PxHitFlag::eMESH_MULTIPLE | INITIAL_OVERLAP, qfd, &SweepCallbackAll(callback, length));
  647. }
  648. }
  649. /******************************************************************************/
  650. #if PX_PHYSICS_VERSION_MAJOR==3 && PX_PHYSICS_VERSION_MINOR==2 && PX_PHYSICS_VERSION_BUGFIX==2
  651. #define MAX_ACTOR_SHAPES 32
  652. /******************************************************************************/
  653. static PxFilterData FilterData[MAX_ACTOR_SHAPES]; // use outside static because 'PxFilterData' has constructor (this can be global because it's never modified)
  654. Bool Actor::sweep(C Vec &move, PhysHit *phys_hit)C
  655. {
  656. struct ActorSweepCallback : PxQueryFilterCallback
  657. {
  658. UInt groups;
  659. PxRigidActor *actor;
  660. ActorSweepCallback(PxRigidActor &actor, UInt groups) {T.actor=&actor; T.groups=groups;}
  661. virtual PxQueryHitType::Enum preFilter(const PxFilterData &filterData, const PxShape *shape, const PxRigidActor *actor, PxHitFlags &queryFlags)
  662. {
  663. return (shape && actor!=shape->getActor() && (shape->getQueryFilterData().word0&groups)) ? PxQueryHitType::eBLOCK : PxQueryHitType::eNONE;
  664. }
  665. virtual PxQueryHitType::Enum postFilter(const PxFilterData &filterData, const PxQueryHit &hit)
  666. {
  667. return PxQueryHitType::eBLOCK; // return BLOCK so first result will be stored in the output buffer (touches would be ignored)
  668. }
  669. };
  670. if(_actor && Physx.world)
  671. {
  672. PxGeometryHolder geom [MAX_ACTOR_SHAPES];
  673. C PxGeometry *geom_ptr[MAX_ACTOR_SHAPES];
  674. PxTransform poses [MAX_ACTOR_SHAPES];
  675. Int shapes=_actor->getNbShapes(), geoms=0;
  676. PxShape *shape;
  677. FREP(shapes)
  678. {
  679. if(!InRange(geoms, MAX_ACTOR_SHAPES))break;
  680. if(_actor->getShapes(&shape, 1, i))switch(shape->getGeometryType())
  681. {
  682. case PxGeometryType::eBOX : if(shape->getBoxGeometry (geom[geoms].box ())){geom_ptr[geoms]=&geom[geoms].box (); poses[geoms]=_actor->getGlobalPose()*shape->getLocalPose(); geoms++;} break;
  683. case PxGeometryType::eSPHERE : if(shape->getSphereGeometry (geom[geoms].sphere ())){geom_ptr[geoms]=&geom[geoms].sphere (); poses[geoms]=_actor->getGlobalPose()*shape->getLocalPose(); geoms++;} break;
  684. case PxGeometryType::eCAPSULE : if(shape->getCapsuleGeometry (geom[geoms].capsule ())){geom_ptr[geoms]=&geom[geoms].capsule (); poses[geoms]=_actor->getGlobalPose()*shape->getLocalPose(); geoms++;} break;
  685. case PxGeometryType::eCONVEXMESH: if(shape->getConvexMeshGeometry(geom[geoms].convexMesh())){geom_ptr[geoms]=&geom[geoms].convexMesh(); poses[geoms]=_actor->getGlobalPose()*shape->getLocalPose(); geoms++;} break;
  686. }
  687. }
  688. if(geoms)
  689. {
  690. Vec dir=move; Flt length=dir.normalize();
  691. ActorSweepCallback asc(*_actor, Physics.collisionGroups(group()));
  692. ReadLock lock(Physics._rws);
  693. if(phys_hit)
  694. {
  695. PxSweepHit hit; if(Physx.world->sweepSingle(geom_ptr, poses, FilterData, geoms, Physx.vec(dir), length, PxHitFlag::ePOSITION | PxHitFlag::eNORMAL | PxHitFlag::eDISTANCE | PxHitFlag::eFACE_INDEX | PxHitFlag::ePRECISE_SWEEP | INITIAL_OVERLAP, hit, PxQueryFlag::eDYNAMIC | PxQueryFlag::eSTATIC | PxQueryFlag::ePREFILTER, &asc)){phys_hit->set(hit, length); return true;}
  696. }else
  697. {
  698. PxQueryHit hit; return Physx.world->sweepAny(geom_ptr, poses, FilterData, geoms, Physx.vec(dir), length, PxHitFlag::ePRECISE_SWEEP | INITIAL_OVERLAP, hit, PxQueryFlag::eDYNAMIC | PxQueryFlag::eSTATIC | PxQueryFlag::ePREFILTER, &asc);
  699. }
  700. }
  701. }
  702. return false;
  703. }
  704. void Actor::sweep(C Vec &move, PhysHitCallback &callback)C
  705. {
  706. struct ActorSweepCallbackAll : PxQueryFilterCallback
  707. {
  708. UInt groups;
  709. Flt move_length;
  710. PxRigidActor *actor;
  711. PhysHitCallback *callback;
  712. ActorSweepCallbackAll(PhysHitCallback &callback, PxRigidActor &actor, UInt groups) : callback(&callback) {T.actor=&actor; T.groups=groups;}
  713. virtual PxQueryHitType::Enum preFilter(const PxFilterData &filterData, const PxShape *shape, const PxRigidActor *actor, PxHitFlags &queryFlags)
  714. {
  715. return (callback && shape && actor!=shape->getActor() && (shape->getQueryFilterData().word0&groups)) ? PxQueryHitType::eTOUCH : PxQueryHitType::eNONE;
  716. }
  717. virtual PxQueryHitType::Enum postFilter(const PxFilterData &filterData, const PxQueryHit &hit)
  718. {
  719. if(callback)
  720. {
  721. C PxSweepHit &sweep_hit=(C PxSweepHit&)hit;
  722. PhysHit phys_hit; phys_hit.set(sweep_hit, move_length); if(!callback->hit(phys_hit))callback=null;
  723. }
  724. return PxQueryHitType::eNONE; // return NONE so it won't need to be stored in the output buffer (which we don't specify)
  725. }
  726. };
  727. if(_actor && Physx.world)
  728. {
  729. PxGeometryHolder geom [MAX_ACTOR_SHAPES];
  730. C PxGeometry *geom_ptr[MAX_ACTOR_SHAPES];
  731. PxTransform poses [MAX_ACTOR_SHAPES];
  732. Int shapes=_actor->getNbShapes(), geoms=0;
  733. PxShape *shape;
  734. FREP(shapes)
  735. {
  736. if(!InRange(geoms, MAX_ACTOR_SHAPES))break;
  737. if(_actor->getShapes(&shape, 1, i))switch(shape->getGeometryType())
  738. {
  739. case PxGeometryType::eBOX : if(shape->getBoxGeometry (geom[geoms].box ())){geom_ptr[geoms]=&geom[geoms].box (); poses[geoms]=_actor->getGlobalPose()*shape->getLocalPose(); geoms++;} break;
  740. case PxGeometryType::eSPHERE : if(shape->getSphereGeometry (geom[geoms].sphere ())){geom_ptr[geoms]=&geom[geoms].sphere (); poses[geoms]=_actor->getGlobalPose()*shape->getLocalPose(); geoms++;} break;
  741. case PxGeometryType::eCAPSULE : if(shape->getCapsuleGeometry (geom[geoms].capsule ())){geom_ptr[geoms]=&geom[geoms].capsule (); poses[geoms]=_actor->getGlobalPose()*shape->getLocalPose(); geoms++;} break;
  742. case PxGeometryType::eCONVEXMESH: if(shape->getConvexMeshGeometry(geom[geoms].convexMesh())){geom_ptr[geoms]=&geom[geoms].convexMesh(); poses[geoms]=_actor->getGlobalPose()*shape->getLocalPose(); geoms++;} break;
  743. }
  744. }
  745. if(geoms)
  746. {
  747. Vec dir=move; Flt length=dir.normalize(); bool blocking;
  748. ActorSweepCallbackAll asc(callback, *_actor, Physics.collisionGroups(group()));
  749. ReadLock lock(Physics._rws);
  750. Physx.world->sweepMultiple(geom_ptr, poses, FilterData, geoms, Physx.vec(dir), length, PxHitFlag::ePOSITION | PxHitFlag::eNORMAL | PxHitFlag::eDISTANCE | PxHitFlag::eFACE_INDEX | PxHitFlag::ePRECISE_SWEEP | PxHitFlag::eMESH_MULTIPLE | INITIAL_OVERLAP, null, 0, blocking, PxQueryFlag::eDYNAMIC | PxQueryFlag::eSTATIC | PxQueryFlag::ePREFILTER | PxQueryFlag::ePOSTFILTER, &asc);
  751. }
  752. }
  753. }
  754. #else
  755. // method taken from "PhysX SDK\Source\PhysXExtensions\src\ExtRigidBodyExt.cpp"
  756. Bool Actor::sweep(C Vec &move, PhysHit *phys_hit, UInt groups)C
  757. {
  758. struct ActorSweepCallback : PxQueryFilterCallback
  759. {
  760. UInt groups;
  761. PxRigidActor *actor;
  762. ActorSweepCallback(PxRigidActor &actor, UInt groups) {T.actor=&actor; T.groups=groups;}
  763. virtual PxQueryHitType::Enum preFilter(const PxFilterData &filterData, const PxShape *shape, const PxRigidActor *actor, PxHitFlags &queryFlags)
  764. {
  765. return (shape && actor!=T.actor && (shape->getQueryFilterData().word0&groups)) ? PxQueryHitType::eBLOCK : PxQueryHitType::eNONE;
  766. }
  767. virtual PxQueryHitType::Enum postFilter(const PxFilterData &filterData, const PxQueryHit &hit)
  768. {
  769. return PxQueryHitType::eBLOCK; // return BLOCK so first result will be stored in the output buffer (touches would be ignored)
  770. }
  771. };
  772. if(_actor && Physx.world && groups)
  773. {
  774. Vec dir=move; Flt length=dir.normalize();
  775. Bool have_hit=false; Flt dist_hit;
  776. PxSweepHit closest_hit;
  777. ActorSweepCallback asc(*_actor, groups);
  778. PxQueryFilterData qfd(PxQueryFlag::eDYNAMIC | PxQueryFlag::eSTATIC | PxQueryFlag::ePREFILTER); qfd.data.word0=asc.groups; if(!phys_hit)qfd.flags|=PxQueryFlag::eANY_HIT;
  779. ReadLock lock(Physics._rws);
  780. REP(_actor->getNbShapes())
  781. {
  782. PxShape *shape=null; _actor->getShapes(&shape, 1, i);
  783. if(shape)
  784. {
  785. PxTransform pose=_actor->getGlobalPose()*shape->getLocalPose();
  786. PxSweepBuffer hit;
  787. if(phys_hit)
  788. {
  789. if(Physx.world->sweep(shape->getGeometry().any(), pose, Physx.vec(dir), length, hit, PxHitFlag::ePOSITION | PxHitFlag::eNORMAL | PxHitFlag::eDISTANCE | PxHitFlag::eFACE_INDEX | PxHitFlag::ePRECISE_SWEEP | INITIAL_OVERLAP, qfd, &asc))
  790. if(!have_hit || hit.block.distance<dist_hit)
  791. {
  792. have_hit=true;
  793. dist_hit=hit.block.distance;
  794. Swap(closest_hit, hit.block);
  795. }
  796. }else
  797. {
  798. if(Physx.world->sweep(shape->getGeometry().any(), pose, Physx.vec(dir), length, hit, PxHitFlag::ePRECISE_SWEEP | PxHitFlag::eMESH_ANY | INITIAL_OVERLAP, qfd, &asc))
  799. {
  800. return true;
  801. }
  802. }
  803. }
  804. }
  805. if(have_hit){phys_hit->set(closest_hit, length); return true;}
  806. }
  807. return false;
  808. }
  809. void Actor::sweep(C Vec &move, PhysHitCallback &callback, UInt groups)C
  810. {
  811. struct ActorSweepCallbackAll : PxQueryFilterCallback
  812. {
  813. UInt groups;
  814. Flt move_length;
  815. PxRigidActor *actor;
  816. PhysHitCallback *callback;
  817. ActorSweepCallbackAll(PhysHitCallback &callback, PxRigidActor &actor, UInt groups) : callback(&callback) {T.actor=&actor; T.groups=groups;}
  818. virtual PxQueryHitType::Enum preFilter(const PxFilterData &filterData, const PxShape *shape, const PxRigidActor *actor, PxHitFlags &queryFlags)
  819. {
  820. return (callback && shape && actor!=T.actor && (shape->getQueryFilterData().word0&groups)) ? PxQueryHitType::eTOUCH : PxQueryHitType::eNONE;
  821. }
  822. virtual PxQueryHitType::Enum postFilter(const PxFilterData &filterData, const PxQueryHit &hit)
  823. {
  824. if(callback)
  825. {
  826. C PxSweepHit &sweep_hit=(C PxSweepHit&)hit;
  827. PhysHit phys_hit; phys_hit.set(sweep_hit, move_length); if(!callback->hit(phys_hit))callback=null;
  828. }
  829. return PxQueryHitType::eNONE; // return NONE so it won't need to be stored in the output buffer (which we don't specify)
  830. }
  831. };
  832. if(_actor && Physx.world && groups)
  833. {
  834. Vec dir=move; Flt length=dir.normalize();
  835. ActorSweepCallbackAll asc(callback, *_actor, groups);
  836. PxQueryFilterData qfd(PxQueryFlag::eDYNAMIC | PxQueryFlag::eSTATIC | PxQueryFlag::ePREFILTER | PxQueryFlag::ePOSTFILTER); qfd.data.word0=asc.groups;
  837. ReadLock lock(Physics._rws);
  838. REP(_actor->getNbShapes())
  839. {
  840. PxShape *shape=null; _actor->getShapes(&shape, 1, i);
  841. if(shape)
  842. {
  843. PxTransform pose=_actor->getGlobalPose()*shape->getLocalPose();
  844. PxSweepBuffer hit;
  845. Physx.world->sweep(shape->getGeometry().any(), pose, Physx.vec(dir), length, hit, PxHitFlag::ePOSITION | PxHitFlag::eNORMAL | PxHitFlag::eDISTANCE | PxHitFlag::eFACE_INDEX | PxHitFlag::ePRECISE_SWEEP | PxHitFlag::eMESH_MULTIPLE | INITIAL_OVERLAP, qfd, &asc);
  846. }
  847. }
  848. }
  849. }
  850. #endif
  851. /******************************************************************************/
  852. #else // BULLET
  853. /******************************************************************************/
  854. static Bool GetFaceNormal(C btBvhTriangleMeshShape &mesh, Int face, Int subpart, C Vec *scale, Vec &normal)
  855. {
  856. Bool ok=false;
  857. if(C btStridingMeshInterface *smi=mesh.getMeshInterface())
  858. if(InRange(subpart, smi->getNumSubParts()))
  859. {
  860. C unsigned char *pos;
  861. C unsigned char *ind;
  862. int vtxs, tris, vtx_stride, ind_stride;
  863. PHY_ScalarType vtx_type, ind_type;
  864. smi->getLockedReadOnlyVertexIndexBase((const unsigned char**)&pos, vtxs, vtx_type, vtx_stride, &ind, ind_stride, tris, ind_type, subpart);
  865. if(InRange(face, tris))
  866. {
  867. VecI v;
  868. switch(ind_type)
  869. {
  870. case PHY_SHORT : v=((VecUS*)ind)[face]; break;
  871. case PHY_INTEGER: v=((VecI *)ind)[face]; break;
  872. default : goto error;
  873. }
  874. switch(vtx_type)
  875. {
  876. case PHY_FLOAT:
  877. {
  878. Vec *p=(Vec*)pos;
  879. if(scale)normal=GetNormal(p[v.x]* *scale, p[v.y]* *scale, p[v.z]* *scale);
  880. else normal=GetNormal(p[v.x] , p[v.y] , p[v.z] );
  881. ok=true;
  882. }break;
  883. case PHY_DOUBLE:
  884. {
  885. VecD *p=(VecD*)pos;
  886. if(scale)normal=GetNormal(p[v.x]* *scale, p[v.y]* *scale, p[v.z]* *scale);
  887. else normal=GetNormal(p[v.x] , p[v.y] , p[v.z] );
  888. ok=true;
  889. }break;
  890. }
  891. }
  892. error:
  893. smi->unLockReadOnlyVertexBase(subpart);
  894. }
  895. return ok;
  896. }
  897. static Bool GetFaceNormal(C btScaledBvhTriangleMeshShape &scaled_mesh, Int face, Int subpart, Vec &normal)
  898. {
  899. if(C btBvhTriangleMeshShape *mesh=scaled_mesh.getChildShape())
  900. return GetFaceNormal(*mesh, face, subpart, &Bullet.vec(scaled_mesh.getLocalScaling()), normal);
  901. return false;
  902. }
  903. static void GetFaceNormal(PhysHit &phys_hit, Int subpart)
  904. {
  905. if(phys_hit.face>=0 && subpart>=0)
  906. if(C btCollisionShape *shape=phys_hit._actor->getCollisionShape())
  907. switch(shape->getShapeType())
  908. {
  909. case TRIANGLE_MESH_SHAPE_PROXYTYPE: if(GetFaceNormal(*( btBvhTriangleMeshShape*)shape, phys_hit.face, subpart, null, phys_hit.face_nrm)){phys_hit.face_nrm*=Bullet.matrix(phys_hit._actor->getWorldTransform().getBasis()); return;} break;
  910. case SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE: if(GetFaceNormal(*(btScaledBvhTriangleMeshShape*)shape, phys_hit.face, subpart, phys_hit.face_nrm)){phys_hit.face_nrm*=Bullet.matrix(phys_hit._actor->getWorldTransform().getBasis()); return;} break;
  911. }
  912. phys_hit.face_nrm=phys_hit.plane.normal;
  913. }
  914. /******************************************************************************/
  915. void ActorInfo::set(RigidBody *actor)
  916. {
  917. if(T._actor=actor)
  918. {
  919. collision=!FlagTest(actor->getCollisionFlags(), btCollisionObject::CF_NO_CONTACT_RESPONSE);
  920. dynamic =!actor->isStaticOrKinematicObject();
  921. group = actor->getBroadphaseProxy()->m_collisionFilterGroup;
  922. user = actor->user;
  923. obj = actor->obj;
  924. }else
  925. {
  926. collision=false;
  927. dynamic =false;
  928. group =0;
  929. user =null;
  930. obj =null;
  931. }
  932. }
  933. /******************************************************************************/
  934. struct ContactResultCallback : btCollisionWorld::ContactResultCallback
  935. {
  936. Bool hit;
  937. UInt groups;
  938. btCollisionObject *test;
  939. virtual bool needsCollision(btBroadphaseProxy *proxy0)C override
  940. {
  941. return Physics.collidesMask(proxy0->m_collisionFilterGroup, groups);
  942. }
  943. virtual btScalar addSingleResult(btManifoldPoint &cp, const btCollisionObjectWrapper *colObj0Wrap, int partId0, int index0, const btCollisionObjectWrapper *colObj1Wrap, int partId1, int index1)override
  944. {
  945. C btCollisionObject &colObj0=*colObj0Wrap->m_collisionObject,
  946. &colObj1=*colObj1Wrap->m_collisionObject;
  947. if((!test || &colObj0!=test) && !FlagTest(colObj0.getCollisionFlags(), btCollisionObject::CF_NO_CONTACT_RESPONSE) // Actor.collision()==true
  948. || (!test || &colObj1!=test) && !FlagTest(colObj1.getCollisionFlags(), btCollisionObject::CF_NO_CONTACT_RESPONSE)) // Actor.collision()==true
  949. {
  950. hit=true;
  951. }
  952. return cp.getDistance();
  953. }
  954. ContactResultCallback(UInt groups, btCollisionObject *test)
  955. {
  956. T.hit =false;
  957. T.groups=groups;
  958. T.test =test;
  959. }
  960. };
  961. struct ContactResultCallbackAll : btCollisionWorld::ContactResultCallback
  962. {
  963. Bool hit;
  964. UInt groups;
  965. PhysCutsCallback *callback;
  966. btCollisionObject *test;
  967. virtual bool needsCollision(btBroadphaseProxy* proxy0)C override
  968. {
  969. return Physics.collidesMask(proxy0->m_collisionFilterGroup, groups);
  970. }
  971. virtual btScalar addSingleResult(btManifoldPoint &cp, const btCollisionObjectWrapper *colObj0Wrap, int partId0, int index0, const btCollisionObjectWrapper* colObj1Wrap, int partId1, int index1)override
  972. {
  973. if(callback)
  974. {
  975. C btCollisionObject &colObj0=*colObj0Wrap->m_collisionObject,
  976. &colObj1=*colObj1Wrap->m_collisionObject;
  977. if(RigidBody *rb=(RigidBody*)((&colObj0!=test) ? colObj0 : colObj1).getUserPointer())
  978. if(!FlagTest(rb->getCollisionFlags(), btCollisionObject::CF_NO_CONTACT_RESPONSE)) // Actor.collision()==true
  979. {
  980. ActorInfo ai; ai.set(rb); if(!callback->hit(ai))callback=null;
  981. }
  982. }
  983. return cp.getDistance();
  984. }
  985. ContactResultCallbackAll(UInt groups, PhysCutsCallback &callback, btCollisionObject &test)
  986. {
  987. T.groups = groups;
  988. T.callback=&callback;
  989. T.test =&test;
  990. }
  991. };
  992. /******************************************************************************/
  993. Bool PhysicsClass::cuts(C Box &box, UInt groups)
  994. {
  995. if(Bullet.world)
  996. {
  997. ContactResultCallback crc(groups, null);
  998. btCollisionObject object; object.setUserPointer(null);
  999. btBoxShape shape(Bullet.vec(box.size()*0.5f));
  1000. object.setCollisionShape(&shape);
  1001. object.setWorldTransform(Bullet.matrix(Matrix(box.center())));
  1002. ReadLock lock(Physics._rws);
  1003. Bullet.world->contactTest(&object, crc);
  1004. return crc.hit;
  1005. }
  1006. return false;
  1007. }
  1008. Bool PhysicsClass::cuts(C OBox &obox, UInt groups)
  1009. {
  1010. if(Bullet.world)
  1011. {
  1012. ContactResultCallback crc(groups, null);
  1013. btCollisionObject object; object.setUserPointer(null);
  1014. btBoxShape shape(Bullet.vec(obox.box.size()*0.5f));
  1015. object.setCollisionShape(&shape);
  1016. object.setWorldTransform(Bullet.matrix(Matrix(obox.matrix.orn(), obox.center())));
  1017. ReadLock lock(Physics._rws);
  1018. Bullet.world->contactTest(&object, crc);
  1019. return crc.hit;
  1020. }
  1021. return false;
  1022. }
  1023. Bool PhysicsClass::cuts(C Ball &ball, UInt groups)
  1024. {
  1025. if(Bullet.world)
  1026. {
  1027. ContactResultCallback crc(groups, null);
  1028. btCollisionObject object; object.setUserPointer(null);
  1029. btSphereShape shape(ball.r);
  1030. object.setCollisionShape(&shape);
  1031. object.setWorldTransform(Bullet.matrix(Matrix(ball.pos)));
  1032. ReadLock lock(Physics._rws);
  1033. Bullet.world->contactTest(&object, crc);
  1034. return crc.hit;
  1035. }
  1036. return false;
  1037. }
  1038. Bool PhysicsClass::cuts(C Capsule &capsule, UInt groups)
  1039. {
  1040. if(Bullet.world)
  1041. {
  1042. ContactResultCallback crc(groups, null);
  1043. btCollisionObject object; object.setUserPointer(null);
  1044. btCapsuleShape shape(capsule.r, capsule.h-capsule.r*2);
  1045. object.setCollisionShape(&shape);
  1046. object.setWorldTransform(Bullet.matrix(Matrix().setPosUp(capsule.pos, capsule.up)));
  1047. ReadLock lock(Physics._rws);
  1048. Bullet.world->contactTest(&object, crc);
  1049. return crc.hit;
  1050. }
  1051. return false;
  1052. }
  1053. /******************************************************************************/
  1054. void PhysicsClass::cuts(C Box &box, PhysCutsCallback &callback, UInt groups)
  1055. {
  1056. if(Bullet.world)
  1057. {
  1058. btCollisionObject object; object.setUserPointer(null);
  1059. btBoxShape shape(Bullet.vec(box.size()*0.5f));
  1060. object.setCollisionShape(&shape);
  1061. object.setWorldTransform(Bullet.matrix(Matrix(box.center())));
  1062. ContactResultCallbackAll cb(groups, callback, object); ReadLock lock(Physics._rws); Bullet.world->contactTest(&object, cb);
  1063. }
  1064. }
  1065. void PhysicsClass::cuts(C OBox &obox, PhysCutsCallback &callback, UInt groups)
  1066. {
  1067. if(Bullet.world)
  1068. {
  1069. btCollisionObject object; object.setUserPointer(null);
  1070. btBoxShape shape(Bullet.vec(obox.box.size()*0.5f));
  1071. object.setCollisionShape(&shape);
  1072. object.setWorldTransform(Bullet.matrix(Matrix(obox.matrix.orn(), obox.center())));
  1073. ContactResultCallbackAll cb(groups, callback, object); ReadLock lock(Physics._rws); Bullet.world->contactTest(&object, cb);
  1074. }
  1075. }
  1076. void PhysicsClass::cuts(C Ball &ball, PhysCutsCallback &callback, UInt groups)
  1077. {
  1078. if(Bullet.world)
  1079. {
  1080. btCollisionObject object; object.setUserPointer(null);
  1081. btSphereShape shape(ball.r);
  1082. object.setCollisionShape(&shape);
  1083. object.setWorldTransform(Bullet.matrix(Matrix(ball.pos)));
  1084. ContactResultCallbackAll cb(groups, callback, object); ReadLock lock(Physics._rws); Bullet.world->contactTest(&object, cb);
  1085. }
  1086. }
  1087. void PhysicsClass::cuts(C Capsule &capsule, PhysCutsCallback &callback, UInt groups)
  1088. {
  1089. if(Bullet.world)
  1090. {
  1091. btCollisionObject object; object.setUserPointer(null);
  1092. btCapsuleShape shape(capsule.r, capsule.h-capsule.r*2);
  1093. object.setCollisionShape(&shape);
  1094. object.setWorldTransform(Bullet.matrix(Matrix().setPosUp(capsule.pos, capsule.up)));
  1095. ContactResultCallbackAll cb(groups, callback, object); ReadLock lock(Physics._rws); Bullet.world->contactTest(&object, cb);
  1096. }
  1097. }
  1098. /******************************************************************************/
  1099. Bool PhysicsClass::ray(C Vec &pos, C Vec &move, PhysHit *phys_hit, UInt groups)
  1100. {
  1101. struct RayResultCallback : btCollisionWorld::RayResultCallback
  1102. {
  1103. Bool hit;
  1104. UInt groups;
  1105. PhysHit *phys_hit;
  1106. Vec pos, move;
  1107. virtual bool needsCollision(btBroadphaseProxy* proxy0) const
  1108. {
  1109. return Physics.collidesMask(proxy0->m_collisionFilterGroup, groups) && proxy0->m_collisionFilterMask!=0; // Actor::ray()==true
  1110. }
  1111. virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult &rayResult, bool normalInWorldSpace)
  1112. {
  1113. if(RigidBody *actor=(RigidBody*)rayResult.m_collisionObject)
  1114. {
  1115. if(phys_hit)if(!hit || rayResult.m_hitFraction<phys_hit->frac)
  1116. {
  1117. phys_hit->set(actor);
  1118. phys_hit->face=(rayResult.m_localShapeInfo ? rayResult.m_localShapeInfo->m_triangleIndex : -1);
  1119. phys_hit->frac=rayResult.m_hitFraction;
  1120. phys_hit->dist=rayResult.m_hitFraction*move.length();
  1121. phys_hit->plane.set(pos+move*rayResult.m_hitFraction, Bullet.vec(normalInWorldSpace ? rayResult.m_hitNormalLocal : rayResult.m_collisionObject->getWorldTransform().getBasis()*rayResult.m_hitNormalLocal));
  1122. GetFaceNormal(*phys_hit, rayResult.m_localShapeInfo ? rayResult.m_localShapeInfo->m_shapePart : -1);
  1123. }
  1124. hit=true;
  1125. }
  1126. return rayResult.m_hitFraction;
  1127. }
  1128. RayResultCallback(PhysHit *phys_hit, C Vec &pos, C Vec &move, UInt groups)
  1129. {
  1130. T.hit =false;
  1131. T.groups =groups;
  1132. T.phys_hit=phys_hit;
  1133. T.pos =pos;
  1134. T.move =move;
  1135. }
  1136. };
  1137. if(Bullet.world)
  1138. {
  1139. RayResultCallback rrc(phys_hit, pos, move, groups);
  1140. ReadLock lock(Physics._rws);
  1141. Bullet.world->rayTest(Bullet.vec(pos), Bullet.vec(pos+move), rrc);
  1142. return rrc.hit;
  1143. }
  1144. return false;
  1145. }
  1146. void PhysicsClass::ray(C Vec &pos, C Vec &move, PhysHitCallback &callback, UInt groups)
  1147. {
  1148. struct RayResultCallbackAll : btCollisionWorld::RayResultCallback
  1149. {
  1150. PhysHit phys_hit;
  1151. UInt groups;
  1152. Vec pos, move;
  1153. PhysHitCallback *callback;
  1154. virtual bool needsCollision(btBroadphaseProxy* proxy0) const
  1155. {
  1156. return Physics.collidesMask(proxy0->m_collisionFilterGroup, groups) && proxy0->m_collisionFilterMask!=0; // Actor::ray()==true
  1157. }
  1158. virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult &rayResult, bool normalInWorldSpace)
  1159. {
  1160. if(callback)if(RigidBody *actor=(RigidBody*)rayResult.m_collisionObject)
  1161. {
  1162. phys_hit.set(actor);
  1163. phys_hit.face=(rayResult.m_localShapeInfo ? rayResult.m_localShapeInfo->m_triangleIndex : -1);
  1164. phys_hit.frac=rayResult.m_hitFraction;
  1165. phys_hit.dist=rayResult.m_hitFraction*move.length();
  1166. phys_hit.plane.set(pos+move*rayResult.m_hitFraction, Bullet.vec(normalInWorldSpace ? rayResult.m_hitNormalLocal : rayResult.m_collisionObject->getWorldTransform().getBasis()*rayResult.m_hitNormalLocal));
  1167. GetFaceNormal(phys_hit, rayResult.m_localShapeInfo ? rayResult.m_localShapeInfo->m_shapePart : -1);
  1168. if(!callback->hit(phys_hit))callback=null;
  1169. }
  1170. return rayResult.m_hitFraction;
  1171. }
  1172. RayResultCallbackAll(C Vec &pos, C Vec &move, PhysHitCallback &callback, UInt groups)
  1173. {
  1174. T.groups = groups;
  1175. T.pos = pos;
  1176. T.move = move;
  1177. T.callback=&callback;
  1178. }
  1179. };
  1180. if(Bullet.world)
  1181. {
  1182. RayResultCallbackAll cb(pos, move, callback, groups);
  1183. ReadLock lock(Physics._rws);
  1184. Bullet.world->rayTest(Bullet.vec(pos), Bullet.vec(pos+move), cb);
  1185. }
  1186. }
  1187. /******************************************************************************/
  1188. struct ConvexResultCallback : btCollisionWorld::ConvexResultCallback
  1189. {
  1190. Bool hit;
  1191. UInt groups;
  1192. Vec move;
  1193. PhysHit *phys_hit;
  1194. virtual bool needsCollision(btBroadphaseProxy* proxy0) const
  1195. {
  1196. return Physics.collidesMask(proxy0->m_collisionFilterGroup, groups);
  1197. }
  1198. virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult, bool normalInWorldSpace)
  1199. {
  1200. if(RigidBody *actor=(RigidBody*)convexResult.m_hitCollisionObject)
  1201. if(!FlagTest(actor->getCollisionFlags(), btCollisionObject::CF_NO_CONTACT_RESPONSE)) // Actor.collision()==true
  1202. {
  1203. if(phys_hit)if(!hit || convexResult.m_hitFraction<phys_hit->frac)
  1204. {
  1205. phys_hit->set(actor);
  1206. phys_hit->face=(convexResult.m_localShapeInfo ? convexResult.m_localShapeInfo->m_triangleIndex : -1);
  1207. phys_hit->frac=convexResult.m_hitFraction;
  1208. phys_hit->dist=convexResult.m_hitFraction*move.length();
  1209. phys_hit->plane.set(Bullet.vec(convexResult.m_hitPointLocal), Bullet.vec(normalInWorldSpace ? convexResult.m_hitNormalLocal : convexResult.m_hitCollisionObject->getWorldTransform().getBasis()*convexResult.m_hitNormalLocal));
  1210. GetFaceNormal(*phys_hit, convexResult.m_localShapeInfo ? convexResult.m_localShapeInfo->m_shapePart : -1);
  1211. }
  1212. hit=true;
  1213. }
  1214. return convexResult.m_hitFraction;
  1215. }
  1216. ConvexResultCallback(C Vec &move, PhysHit *phys_hit, UInt groups)
  1217. {
  1218. T.hit =false;
  1219. T.move =move;
  1220. T.phys_hit=phys_hit;
  1221. T.groups =groups;
  1222. }
  1223. };
  1224. Bool PhysicsClass::sweep(C Box &box, C Vec &move, PhysHit *phys_hit, UInt groups)
  1225. {
  1226. if(Bullet.world)
  1227. {
  1228. btTransform from=Bullet.matrix(Matrix(box.center())),
  1229. to =from; to.getOrigin()+=Bullet.vec(move);
  1230. ConvexResultCallback crc(move, phys_hit, groups);
  1231. ReadLock lock(Physics._rws);
  1232. Bullet.world->convexSweepTest(&btBoxShape(Bullet.vec(box.size()*0.5f)), from, to, crc);
  1233. return crc.hit;
  1234. }
  1235. return false;
  1236. }
  1237. Bool PhysicsClass::sweep(C OBox &obox, C Vec &move, PhysHit *phys_hit, UInt groups)
  1238. {
  1239. if(Bullet.world)
  1240. {
  1241. btTransform from=Bullet.matrix(Matrix(obox.matrix.orn(), obox.center())),
  1242. to =from; to.getOrigin()+=Bullet.vec(move);
  1243. ConvexResultCallback crc(move, phys_hit, groups);
  1244. ReadLock lock(Physics._rws);
  1245. Bullet.world->convexSweepTest(&btBoxShape(Bullet.vec(obox.box.size()*0.5f)), from, to, crc);
  1246. return crc.hit;
  1247. }
  1248. return false;
  1249. }
  1250. Bool PhysicsClass::sweep(C Ball &ball, C Vec &move, PhysHit *phys_hit, UInt groups)
  1251. {
  1252. if(Bullet.world)
  1253. {
  1254. btTransform from=Bullet.matrix(Matrix(ball.pos)),
  1255. to =from; to.getOrigin()+=Bullet.vec(move);
  1256. ConvexResultCallback crc(move, phys_hit, groups);
  1257. ReadLock lock(Physics._rws);
  1258. Bullet.world->convexSweepTest(&btSphereShape(ball.r), from, to, crc);
  1259. return crc.hit;
  1260. }
  1261. return false;
  1262. }
  1263. Bool PhysicsClass::sweep(C Capsule &capsule, C Vec &move, PhysHit *phys_hit, UInt groups)
  1264. {
  1265. if(Bullet.world)
  1266. {
  1267. btTransform from=Bullet.matrix(Matrix().setPosUp(capsule.pos, capsule.up)),
  1268. to =from; to.getOrigin()+=Bullet.vec(move);
  1269. ConvexResultCallback crc(move, phys_hit, groups);
  1270. ReadLock lock(Physics._rws);
  1271. Bullet.world->convexSweepTest(&btCapsuleShape(capsule.r, capsule.h-capsule.r*2), from, to, crc);
  1272. return crc.hit;
  1273. }
  1274. return false;
  1275. }
  1276. /******************************************************************************/
  1277. struct ConvexResultCallbackAll : btCollisionWorld::ConvexResultCallback
  1278. {
  1279. UInt groups;
  1280. Vec move;
  1281. PhysHit phys_hit;
  1282. PhysHitCallback *callback;
  1283. virtual bool needsCollision(btBroadphaseProxy* proxy0) const
  1284. {
  1285. return Physics.collidesMask(proxy0->m_collisionFilterGroup, groups);
  1286. }
  1287. virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult, bool normalInWorldSpace)
  1288. {
  1289. if(callback)
  1290. if(RigidBody *actor=(RigidBody*)convexResult.m_hitCollisionObject)
  1291. if(!FlagTest(actor->getCollisionFlags(), btCollisionObject::CF_NO_CONTACT_RESPONSE)) // Actor.collision()==true
  1292. {
  1293. phys_hit.set(actor);
  1294. phys_hit.face=(convexResult.m_localShapeInfo ? convexResult.m_localShapeInfo->m_triangleIndex : -1);
  1295. phys_hit.frac=convexResult.m_hitFraction;
  1296. phys_hit.dist=convexResult.m_hitFraction*move.length();
  1297. phys_hit.plane.set(Bullet.vec(convexResult.m_hitPointLocal), Bullet.vec(normalInWorldSpace ? convexResult.m_hitNormalLocal : convexResult.m_hitCollisionObject->getWorldTransform().getBasis()*convexResult.m_hitNormalLocal));
  1298. GetFaceNormal(phys_hit, convexResult.m_localShapeInfo ? convexResult.m_localShapeInfo->m_shapePart : -1);
  1299. if(!callback->hit(phys_hit))callback=null;
  1300. }
  1301. return convexResult.m_hitFraction;
  1302. }
  1303. ConvexResultCallbackAll(C Vec &move, PhysHitCallback &callback, UInt groups)
  1304. {
  1305. T.move = move;
  1306. T.callback=&callback;
  1307. T.groups = groups;
  1308. }
  1309. };
  1310. void PhysicsClass::sweep(C Box &box, C Vec &move, PhysHitCallback &callback, UInt groups)
  1311. {
  1312. if(Bullet.world)
  1313. {
  1314. btTransform from=Bullet.matrix(Matrix(box.center())),
  1315. to =from; to.getOrigin()+=Bullet.vec(move);
  1316. ConvexResultCallbackAll cb(move, callback, groups); ReadLock lock(Physics._rws); Bullet.world->convexSweepTest(&btBoxShape(Bullet.vec(box.size()*0.5f)), from, to, cb);
  1317. }
  1318. }
  1319. void PhysicsClass::sweep(C OBox &obox, C Vec &move, PhysHitCallback &callback, UInt groups)
  1320. {
  1321. if(Bullet.world)
  1322. {
  1323. btTransform from=Bullet.matrix(Matrix(obox.matrix.orn(), obox.center())),
  1324. to =from; to.getOrigin()+=Bullet.vec(move);
  1325. ConvexResultCallbackAll cb(move, callback, groups); ReadLock lock(Physics._rws); Bullet.world->convexSweepTest(&btBoxShape(Bullet.vec(obox.box.size()*0.5f)), from, to, cb);
  1326. }
  1327. }
  1328. void PhysicsClass::sweep(C Ball &ball, C Vec &move, PhysHitCallback &callback, UInt groups)
  1329. {
  1330. if(Bullet.world)
  1331. {
  1332. btTransform from=Bullet.matrix(Matrix(ball.pos)),
  1333. to =from; to.getOrigin()+=Bullet.vec(move);
  1334. ConvexResultCallbackAll cb(move, callback, groups); ReadLock lock(Physics._rws); Bullet.world->convexSweepTest(&btSphereShape(ball.r), from, to, cb);
  1335. }
  1336. }
  1337. void PhysicsClass::sweep(C Capsule &capsule, C Vec &move, PhysHitCallback &callback, UInt groups)
  1338. {
  1339. if(Bullet.world)
  1340. {
  1341. btTransform from=Bullet.matrix(Matrix().setPosUp(capsule.pos, capsule.up)),
  1342. to =from; to.getOrigin()+=Bullet.vec(move);
  1343. ConvexResultCallbackAll cb(move, callback, groups); ReadLock lock(Physics._rws); Bullet.world->convexSweepTest(&btCapsuleShape(capsule.r, capsule.h-capsule.r*2), from, to, cb);
  1344. }
  1345. }
  1346. /******************************************************************************/
  1347. Bool Actor::cuts(UInt groups)C
  1348. {
  1349. if(_actor && Bullet.world)
  1350. {
  1351. ContactResultCallback crc(groups, _actor);
  1352. ReadLock lock(Physics._rws);
  1353. Bullet.world->contactTest(_actor, crc);
  1354. return crc.hit;
  1355. }
  1356. return false;
  1357. }
  1358. void Actor::cuts(PhysCutsCallback &callback, UInt groups)C
  1359. {
  1360. if(_actor && Bullet.world)
  1361. {
  1362. ContactResultCallbackAll cb(groups, callback, *_actor); ReadLock lock(Physics._rws); Bullet.world->contactTest(_actor, cb);
  1363. }
  1364. }
  1365. Bool Actor::sweep(C Vec &move, PhysHit *phys_hit, UInt groups)C
  1366. {
  1367. struct ActorConvexResultCallback : btCollisionWorld::ConvexResultCallback
  1368. {
  1369. Bool hit;
  1370. UInt groups;
  1371. C Actor *actor;
  1372. PhysHit *phys_hit;
  1373. Vec move;
  1374. virtual bool needsCollision(btBroadphaseProxy* proxy0) const
  1375. {
  1376. return Physics.collidesMask(proxy0->m_collisionFilterGroup, groups) // collisions enabled between groups
  1377. && actor->_actor->getBroadphaseProxy()!=proxy0; // this is not the same actor
  1378. }
  1379. virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult, bool normalInWorldSpace)
  1380. {
  1381. if(RigidBody *actor=(RigidBody*)convexResult.m_hitCollisionObject)
  1382. if(!FlagTest(actor->getCollisionFlags(), btCollisionObject::CF_NO_CONTACT_RESPONSE)) // Actor.collision()==true
  1383. {
  1384. if(phys_hit)if(!hit || convexResult.m_hitFraction<phys_hit->frac)
  1385. {
  1386. phys_hit->set(actor);
  1387. phys_hit->face=(convexResult.m_localShapeInfo ? convexResult.m_localShapeInfo->m_triangleIndex : -1);
  1388. phys_hit->frac=convexResult.m_hitFraction;
  1389. phys_hit->dist=convexResult.m_hitFraction*move.length();
  1390. phys_hit->plane.set(Bullet.vec(convexResult.m_hitPointLocal), Bullet.vec(normalInWorldSpace ? convexResult.m_hitNormalLocal : convexResult.m_hitCollisionObject->getWorldTransform().getBasis()*convexResult.m_hitNormalLocal));
  1391. GetFaceNormal(*phys_hit, convexResult.m_localShapeInfo ? convexResult.m_localShapeInfo->m_shapePart : -1);
  1392. }
  1393. hit=true;
  1394. }
  1395. return convexResult.m_hitFraction;
  1396. }
  1397. ActorConvexResultCallback(C Actor &actor, PhysHit *phys_hit, C Vec &move, UInt groups)
  1398. {
  1399. T.hit = false ;
  1400. T.groups = groups ;
  1401. T.actor =&actor ;
  1402. T.phys_hit= phys_hit;
  1403. T.move = move ;
  1404. }
  1405. Bool test(btConvexShape *convex, C Matrix &matrix)
  1406. {
  1407. btTransform from=Bullet.matrix(matrix),
  1408. to =from; to.getOrigin()+=Bullet.vec(move);
  1409. Bullet.world->convexSweepTest(convex, from, to, T);
  1410. return hit;
  1411. }
  1412. };
  1413. if(_actor && Bullet.world && groups)
  1414. {
  1415. ActorConvexResultCallback crc(T, phys_hit, move, groups);
  1416. Matrix matrix=T.matrix();
  1417. ReadLock lock(Physics._rws);
  1418. if(btCompoundShape *compound=CAST(btCompoundShape, _actor->getCollisionShape())) // built from many shapes
  1419. {
  1420. REP(compound->getNumChildShapes()) // test all shapes
  1421. if(btConvexShape *convex=CAST(btConvexShape, compound->getChildShape(i))) // if it's convex
  1422. if(crc.test(convex, Bullet.matrix(compound->getChildTransform(i))*matrix)) // if collision has encountered
  1423. if(!phys_hit)return true; // if we're not interested in precise 'phys_hit' info, then return on first collision
  1424. }else
  1425. if(btConvexShape *convex=CAST(btConvexShape, _actor->getCollisionShape())) // if it's convex
  1426. {
  1427. crc.test(convex, matrix);
  1428. }
  1429. return crc.hit;
  1430. }
  1431. return false;
  1432. }
  1433. void Actor::sweep(C Vec &move, PhysHitCallback &callback, UInt groups)C
  1434. {
  1435. struct ActorConvexResultCallbackAll : btCollisionWorld::ConvexResultCallback
  1436. {
  1437. Vec move;
  1438. UInt groups;
  1439. C Actor *actor;
  1440. PhysHit phys_hit;
  1441. PhysHitCallback *callback;
  1442. virtual bool needsCollision(btBroadphaseProxy* proxy0) const
  1443. {
  1444. return Physics.collidesMask(proxy0->m_collisionFilterGroup, groups) // collisions enabled between groups
  1445. && actor->_actor->getBroadphaseProxy()!=proxy0; // this is not the same actor
  1446. }
  1447. virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult, bool normalInWorldSpace)
  1448. {
  1449. if(callback)
  1450. if(RigidBody *actor=(RigidBody*)convexResult.m_hitCollisionObject)
  1451. if(!FlagTest(actor->getCollisionFlags(), btCollisionObject::CF_NO_CONTACT_RESPONSE)) // Actor.collision()==true
  1452. {
  1453. phys_hit.set(actor);
  1454. phys_hit.face=(convexResult.m_localShapeInfo ? convexResult.m_localShapeInfo->m_triangleIndex : -1);
  1455. phys_hit.frac=convexResult.m_hitFraction;
  1456. phys_hit.dist=convexResult.m_hitFraction*move.length();
  1457. phys_hit.plane.set(Bullet.vec(convexResult.m_hitPointLocal), Bullet.vec(normalInWorldSpace ? convexResult.m_hitNormalLocal : convexResult.m_hitCollisionObject->getWorldTransform().getBasis()*convexResult.m_hitNormalLocal));
  1458. GetFaceNormal(phys_hit, convexResult.m_localShapeInfo ? convexResult.m_localShapeInfo->m_shapePart : -1);
  1459. if(!callback->hit(phys_hit))callback=null;
  1460. }
  1461. return convexResult.m_hitFraction;
  1462. }
  1463. ActorConvexResultCallbackAll(C Actor &actor, C Vec &move, UInt groups, PhysHitCallback &callback)
  1464. {
  1465. T.groups = groups ;
  1466. T.actor =&actor ;
  1467. T.move = move ;
  1468. T.callback=&callback;
  1469. }
  1470. void test(btConvexShape *convex, C Matrix &matrix)
  1471. {
  1472. btTransform from=Bullet.matrix(matrix),
  1473. to =from; to.getOrigin()+=Bullet.vec(move);
  1474. Bullet.world->convexSweepTest(convex, from, to, T);
  1475. }
  1476. };
  1477. if(_actor && Bullet.world && groups)
  1478. {
  1479. ActorConvexResultCallbackAll crc(T, move, groups, callback);
  1480. Matrix matrix=T.matrix();
  1481. ReadLock lock(Physics._rws);
  1482. if(btCompoundShape *compound=CAST(btCompoundShape, _actor->getCollisionShape())) // built from many shapes
  1483. {
  1484. REP(compound->getNumChildShapes()) // test all shapes
  1485. if(btConvexShape *convex=CAST(btConvexShape, compound->getChildShape(i))) // if it's convex
  1486. crc.test(convex, Bullet.matrix(compound->getChildTransform(i))*matrix);
  1487. }else
  1488. if(btConvexShape *convex=CAST(btConvexShape, _actor->getCollisionShape())) // if it's convex
  1489. {
  1490. crc.test(convex, matrix);
  1491. }
  1492. }
  1493. }
  1494. /******************************************************************************/
  1495. #endif
  1496. /******************************************************************************/
  1497. Bool PhysicsClass::cuts(C Shape &shape, UInt groups)
  1498. {
  1499. switch(shape.type)
  1500. {
  1501. case SHAPE_BOX : return cuts(shape.box , groups);
  1502. case SHAPE_OBOX : return cuts(shape.obox , groups);
  1503. case SHAPE_BALL : return cuts(shape.ball , groups);
  1504. case SHAPE_CAPSULE: return cuts(shape.capsule, groups);
  1505. default : return false;
  1506. }
  1507. }
  1508. /******************************************************************************/
  1509. void PhysicsClass::cuts(C Shape &shape, PhysCutsCallback &callback, UInt groups)
  1510. {
  1511. switch(shape.type)
  1512. {
  1513. case SHAPE_BOX : cuts(shape.box , callback, groups); break;
  1514. case SHAPE_OBOX : cuts(shape.obox , callback, groups); break;
  1515. case SHAPE_BALL : cuts(shape.ball , callback, groups); break;
  1516. case SHAPE_CAPSULE: cuts(shape.capsule, callback, groups); break;
  1517. }
  1518. }
  1519. /******************************************************************************/
  1520. Bool PhysicsClass::sweep(C Shape &shape, C Vec &move, PhysHit *phys_hit, UInt groups)
  1521. {
  1522. switch(shape.type)
  1523. {
  1524. case SHAPE_BOX : return sweep(shape.box , move, phys_hit, groups);
  1525. case SHAPE_OBOX : return sweep(shape.obox , move, phys_hit, groups);
  1526. case SHAPE_BALL : return sweep(shape.ball , move, phys_hit, groups);
  1527. case SHAPE_CAPSULE: return sweep(shape.capsule, move, phys_hit, groups);
  1528. default : return false;
  1529. }
  1530. }
  1531. /******************************************************************************/
  1532. void PhysicsClass::sweep(C Shape &shape, C Vec &move, PhysHitCallback &callback, UInt groups)
  1533. {
  1534. switch(shape.type)
  1535. {
  1536. case SHAPE_BOX : sweep(shape.box , move, callback, groups); break;
  1537. case SHAPE_OBOX : sweep(shape.obox , move, callback, groups); break;
  1538. case SHAPE_BALL : sweep(shape.ball , move, callback, groups); break;
  1539. case SHAPE_CAPSULE: sweep(shape.capsule, move, callback, groups); break;
  1540. }
  1541. }
  1542. /******************************************************************************/
  1543. // MOVE
  1544. /******************************************************************************/
  1545. void PhysicsClass::move(Box &box , C Vec &move, UInt groups) {PhysHit hit; if(sweep(box , move, &hit, groups))box +=move*hit.frac;else box +=move;}
  1546. void PhysicsClass::move(OBox &obox , C Vec &move, UInt groups) {PhysHit hit; if(sweep(obox , move, &hit, groups))obox +=move*hit.frac;else obox +=move;}
  1547. void PhysicsClass::move(Ball &ball , C Vec &move, UInt groups) {PhysHit hit; if(sweep(ball , move, &hit, groups))ball +=move*hit.frac;else ball +=move;}
  1548. void PhysicsClass::move(Capsule &capsule, C Vec &move, UInt groups) {PhysHit hit; if(sweep(capsule, move, &hit, groups))capsule+=move*hit.frac;else capsule+=move;}
  1549. void PhysicsClass::move(Shape &shape , C Vec &move, UInt groups) {PhysHit hit; if(sweep(shape , move, &hit, groups))shape +=move*hit.frac;else shape +=move;}
  1550. /******************************************************************************/
  1551. }
  1552. /******************************************************************************/