TDME2  1.9.200
World.cpp
Go to the documentation of this file.
2 
3 #include <algorithm>
4 #include <iostream>
5 #include <map>
6 #include <memory>
7 #include <string>
8 #include <unordered_set>
9 
10 #include <reactphysics3d/utils/DefaultLogger.h>
11 
12 #include <reactphysics3d/collision/shapes/AABB.h>
13 #include <reactphysics3d/collision/ContactManifold.h>
14 #include <reactphysics3d/collision/OverlapCallback.h>
15 #include <reactphysics3d/collision/RaycastInfo.h>
16 #include <reactphysics3d/constraint/ContactPoint.h>
17 #include <reactphysics3d/constraint/FixedJoint.h>
18 #include <reactphysics3d/constraint/Joint.h>
19 #include <reactphysics3d/engine/PhysicsWorld.h>
20 #include <reactphysics3d/engine/EventListener.h>
21 #include <reactphysics3d/mathematics/Ray.h>
22 #include <reactphysics3d/mathematics/Vector3.h>
23 
24 #include <tdme/tdme.h>
34 #include <tdme/engine/Engine.h>
35 #include <tdme/engine/Entity.h>
36 #include <tdme/engine/Rotation.h>
37 #include <tdme/engine/Transform.h>
38 #include <tdme/math/Math.h>
39 #include <tdme/math/Matrix4x4.h>
40 #include <tdme/math/Quaternion.h>
41 #include <tdme/math/Vector3.h>
42 #include <tdme/utilities/Console.h>
44 #include <tdme/utilities/Time.h>
45 
46 using std::find;
47 using std::make_unique;
48 using std::map;
49 using std::remove;
50 using std::string;
51 using std::to_string;
52 using std::unordered_set;
53 
68 using tdme::math::Math;
75 
76 World::World(const string& id)
77 {
78  //
79  reactphysics3d::PhysicsWorld::WorldSettings worldSettings;
80  worldSettings.worldName = id;
81 
82  //
83  world = physicsCommon.createPhysicsWorld(worldSettings);
84 }
85 
87 {
88  //
89  worldListeners.clear();
90  reset();
91  physicsCommon.destroyPhysicsWorld(world);
92 }
93 
95 {
96  // joints
97  {
98  vector<string> jointIds;
99  for (const auto& [jointId, joint]: jointsById) jointIds.push_back(jointId);
100  for (const auto& jointId: jointIds) removeJoint(jointId);
101  }
102  // bodies
103  {
104  auto _bodies = bodies;
105  for (auto body: _bodies) removeBody(body->getId());
106  bodyCollisionsLastFrame.clear();
107  }
108 }
109 
110 Body* World::addRigidBody(const string& id, uint16_t collisionTypeId, bool enabled, const Transform& transform, float restitution, float friction, float mass, const Vector3& inertiaTensor, const vector<BoundingVolume*>& boundingVolumes, bool hierarchy)
111 {
112  removeBody(id);
113  //
114  auto body =
115  hierarchy == true?
116  new BodyHierarchy(this, id, Body::BODYTYPE_DYNAMIC, collisionTypeId, enabled, transform, restitution, friction, mass, inertiaTensor):
117  new Body(this, id, Body::BODYTYPE_DYNAMIC, collisionTypeId, enabled, transform, restitution, friction, mass, inertiaTensor, boundingVolumes);
118  //
119  if (hierarchy == true) {
120  static_cast<BodyHierarchy*>(body)->addBody(id, Transform(), boundingVolumes);
121  static_cast<BodyHierarchy*>(body)->update();
122  }
123  //
124  bodies.push_back(body);
125  rigidBodiesDynamic.push_back(body);
126  bodiesById[id] = body;
127  //
128  for (auto listener: worldListeners) {
129  listener->onAddedBody(id, Body::BODYTYPE_DYNAMIC, collisionTypeId, enabled, transform, restitution, friction, mass, inertiaTensor, boundingVolumes);
130  }
131  //
132  return body;
133 }
134 
135 Body* World::addStaticCollisionBody(const string& id, uint16_t collisionTypeId, bool enabled, const Transform& transform, const vector<BoundingVolume*>& boundingVolumes, bool hierarchy) {
136  removeBody(id);
137  //
138  auto body =
139  hierarchy == true?
140  new BodyHierarchy(this, id, Body::BODYTYPE_COLLISION_STATIC, collisionTypeId, enabled, transform, 0.0f, 0.0f, 0.0f, Body::getNoRotationInertiaTensor()):
141  new Body(this, id, Body::BODYTYPE_COLLISION_STATIC, collisionTypeId, enabled, transform, 0.0f, 0.0f, 0.0f, Body::getNoRotationInertiaTensor(), boundingVolumes);
142  //
143  if (hierarchy == true) {
144  static_cast<BodyHierarchy*>(body)->addBody(id, Transform(), boundingVolumes);
145  static_cast<BodyHierarchy*>(body)->update();
146  }
147  //
148  bodies.push_back(body);
149  bodiesById[id] = body;
150  //
151  for (auto listener: worldListeners) {
152  listener->onAddedBody(id, Body::BODYTYPE_COLLISION_STATIC, collisionTypeId, enabled, transform, 0.0f, 0.0f, 0.0f, Body::getNoRotationInertiaTensor(), boundingVolumes);
153  }
154  //
155  return body;
156 }
157 
158 Body* World::addDynamicCollisionBody(const string& id, uint16_t collisionTypeId, bool enabled, const Transform& transform, const vector<BoundingVolume*>& boundingVolumes, bool hierarchy) {
159  removeBody(id);
160  //
161  auto body =
162  hierarchy == true?
163  new BodyHierarchy(this, id, Body::BODYTYPE_COLLISION_DYNAMIC, collisionTypeId, enabled, transform, 0.0f, 0.0f, 0.0f, Body::getNoRotationInertiaTensor()):
164  new Body(this, id, Body::BODYTYPE_COLLISION_DYNAMIC, collisionTypeId, enabled, transform, 0.0f, 0.0f, 0.0f, Body::getNoRotationInertiaTensor(), boundingVolumes);
165  //
166  if (hierarchy == true) {
167  static_cast<BodyHierarchy*>(body)->addBody(id, Transform(), boundingVolumes);
168  static_cast<BodyHierarchy*>(body)->update();
169  }
170  //
171  bodies.push_back(body);
172  bodiesById[id] = body;
173  //
174  for (auto listener: worldListeners) {
175  listener->onAddedBody(id, Body::BODYTYPE_COLLISION_DYNAMIC, collisionTypeId, enabled, transform, 0.0f, 0.0f, 0.0f, Body::getNoRotationInertiaTensor(), boundingVolumes);
176  }
177  //
178  return body;
179 }
180 
181 Body* World::addStaticRigidBody(const string& id, uint16_t collisionTypeId, bool enabled, const Transform& transform, float friction, const vector<BoundingVolume*>& boundingVolumes, bool hierarchy)
182 {
183  removeBody(id);
184  //
185  auto body =
186  hierarchy == true?
187  new BodyHierarchy(this, id, Body::BODYTYPE_STATIC, collisionTypeId, enabled, transform, 0.0f, friction, 0.0f, Body::getNoRotationInertiaTensor()):
188  new Body(this, id, Body::BODYTYPE_STATIC, collisionTypeId, enabled, transform, 0.0f, friction, 0.0f, Body::getNoRotationInertiaTensor(), boundingVolumes);
189  //
190  if (hierarchy == true) {
191  static_cast<BodyHierarchy*>(body)->addBody(id, Transform(), boundingVolumes);
192  static_cast<BodyHierarchy*>(body)->update();
193  }
194  //
195  bodies.push_back(body);
196  bodiesById[id] = body;
197  //
198  for (auto listener: worldListeners) {
199  listener->onAddedBody(id, Body::BODYTYPE_STATIC, collisionTypeId, enabled, transform, 0.0f, friction, 0.0f, Body::getNoRotationInertiaTensor(), boundingVolumes);
200  }
201  //
202  return body;
203 }
204 
206  auto body = getBody(id);
207  if (body == nullptr) return nullptr;
208  return dynamic_cast<BodyHierarchy*>(body);
209 }
210 
211 void World::removeBody(const string& id) {
212  auto bodyByIdIt = bodiesById.find(id);
213  if (bodyByIdIt != bodiesById.end()) {
214  auto body = bodyByIdIt->second;
215  bodies.erase(remove(bodies.begin(), bodies.end(), body), bodies.end());
216  rigidBodiesDynamic.erase(remove(rigidBodiesDynamic.begin(), rigidBodiesDynamic.end(), body), rigidBodiesDynamic.end());
217  bodiesById.erase(bodyByIdIt);
218  for (auto listener: worldListeners) {
219  listener->onRemovedBody(id, body->getType(), body->getCollisionTypeId());
220  }
221  //
222  delete body;
223  }
224 }
225 
226 void World::addFixedJoint(const string& id, Body* body1, Body* body2) {
227  removeJoint(id);
228  if (body1->rigidBody == nullptr) {
229  Console::println("World::createFixedJoint(): body1: no rigid body attached");
230  return;
231  } else
232  if (body2->rigidBody == nullptr) {
233  Console::println("World::createFixedJoint(): body2: no rigid body attached");
234  return;
235  }
236  Vector3 anchorPoint = body1->getTransform().getTranslation().clone().add(body2->getTransform().getTranslation()).scale(0.5f);
237  reactphysics3d::FixedJointInfo jointInfo(body1->rigidBody, body2->rigidBody, reactphysics3d::Vector3(anchorPoint.getX(), anchorPoint.getY(), anchorPoint.getZ()));
238  jointInfo.isCollisionEnabled = false;
239  jointsById[id] = dynamic_cast<reactphysics3d::FixedJoint*>(world->createJoint(jointInfo));
240 }
241 
242 void World::removeJoint(const string& id) {
243  auto jointByIdIt = jointsById.find(id);
244  if (jointByIdIt != jointsById.end()) {
245  auto joint = jointByIdIt->second;
246  world->destroyJoint(joint);
247  jointsById.erase(jointByIdIt);
248  }
249 }
250 
251 void World::update(float deltaTime)
252 {
253  if (deltaTime < Math::EPSILON) return;
254 
255  // do the job
256  world->update(deltaTime);
257 
258  /*
259  // TODO: collision events
260  // collision events
261  {
262  // fire on collision begin, on collision
263  map<string, BodyCollisionStruct> bodyCollisionsCurrentFrame;
264  CollisionResponse collision;
265  auto manifolds = world->getContactsList();
266  for (auto manifold: manifolds) {
267  auto body1 = static_cast<Body*>(manifold->getBody1()->getUserData());
268  auto body2 = static_cast<Body*>(manifold->getBody2()->getUserData());
269  BodyCollisionStruct bodyCollisionStruct;
270  bodyCollisionStruct.body1Id = body1->getId();
271  bodyCollisionStruct.body2Id = body2->getId();
272  string bodyKey = bodyCollisionStruct.body1Id + "," + bodyCollisionStruct.body2Id;
273  string bodyKeyInverted = bodyCollisionStruct.body2Id + "," + bodyCollisionStruct.body1Id;
274  bodyCollisionsCurrentFrame[bodyKey] = bodyCollisionStruct;
275  for (int i=0; i<manifold->getNbContactPoints(); i++) {
276  auto contactPoint = manifold->getContactPoints();
277  while (contactPoint != nullptr) {
278  // construct collision
279  auto entity = collision.addResponse(-contactPoint->getPenetrationDepth());
280  auto normal = contactPoint->getNormal();
281  entity->setNormal(Vector3(normal.x, normal.y, normal.z));
282  auto shape1 = manifold->getShape1();
283  auto shape2 = manifold->getShape2();
284  auto shapeLocalToWorldTransform1 = shape1->getLocalToWorldTransform();
285  auto shapeLocalToWorldTransform2 = shape2->getLocalToWorldTransform();
286  auto& localPoint1 = contactPoint->getLocalPointOnShape1();
287  auto& localPoint2 = contactPoint->getLocalPointOnShape2();
288  auto worldPoint1 = shapeLocalToWorldTransform1 * localPoint1;
289  auto worldPoint2 = shapeLocalToWorldTransform2 * localPoint2;
290  entity->addHitPoint(Vector3(worldPoint1.x, worldPoint1.y, worldPoint1.z));
291  entity->addHitPoint(Vector3(worldPoint2.x, worldPoint2.y, worldPoint2.z));
292  contactPoint = contactPoint->getNext();
293  // fire events
294  if (bodyCollisionsLastFrame.find(bodyKey) == bodyCollisionsLastFrame.end() &&
295  bodyCollisionsLastFrame.find(bodyKeyInverted) == bodyCollisionsLastFrame.end()) {
296  // fire on collision begin
297  body1->fireOnCollisionBegin(body2, collision);
298  }
299  // fire on collision
300  body1->fireOnCollision(body2, collision);
301  // reset collision
302  collision.reset();
303  }
304  }
305  }
306 
307  // fire on collision end
308  // check each collision last frame that disappeared in current frame
309  for (auto it: bodyCollisionsLastFrame) {
310  BodyCollisionStruct* bodyCollisionStruct = &it.second;
311  {
312  string bodyKey = bodyCollisionStruct->body1Id + "," + bodyCollisionStruct->body2Id;
313  auto bodyCollisionsCurrentFrameIt = bodyCollisionsCurrentFrame.find(bodyKey);
314  if (bodyCollisionsCurrentFrameIt != bodyCollisionsCurrentFrame.end()) continue;
315  }
316  {
317  string bodyKey = bodyCollisionStruct->body2Id + "," + bodyCollisionStruct->body1Id;
318  auto bodyCollisionsCurrentFrameIt = bodyCollisionsCurrentFrame.find(bodyKey);
319  if (bodyCollisionsCurrentFrameIt != bodyCollisionsCurrentFrame.end()) continue;
320  }
321  auto body1It = bodiesById.find(bodyCollisionStruct->body1Id);
322  auto body1 = body1It == bodiesById.end()?nullptr:body1It->second;
323  auto body2It = bodiesById.find(bodyCollisionStruct->body2Id);
324  auto body2 = body2It == bodiesById.end()?nullptr:body2It->second;
325  if (body1 == nullptr || body2 == nullptr) continue;
326  body1->fireOnCollisionEnd(body2);
327  }
328  // swap rigid body collisions current and last frame
329  bodyCollisionsLastFrame = bodyCollisionsCurrentFrame;
330  }
331  */
332 
333  // update transform for rigid body
334  for (auto body: rigidBodiesDynamic) {
335  // skip if disabled
336  if (body->isEnabled() == false) {
337  continue;
338  }
339  // skip if static or sleeping
340  if (body->isSleeping() == true) {
341  continue;
342  }
343 
344  // rp3d transform
345  const auto& transform = body->rigidBody->getTransform();
346  const auto& transformPosition = transform.getPosition();
347  const auto& transformOrientation = transform.getOrientation();
348 
349  // tdme2 transform
350  auto& physicsTransform = body->transform;
351 
352  // rotations
353  // keep care that only 1 rotation exists
354  while (physicsTransform.getRotationCount() > 1) {
355  physicsTransform.removeRotation(physicsTransform.getRotationCount() - 1);
356  }
357  if (physicsTransform.getRotationCount() < 1) {
358  physicsTransform.addRotation(Vector3(0.0f, 1.0f, 0.0f), 0.0f);
359  }
360 
361  // rotations
362  physicsTransform.getRotation(0).fromRotation(
364  Quaternion(
365  transformOrientation.x,
366  transformOrientation.y,
367  transformOrientation.z,
368  transformOrientation.w
369  )
370  )
371  );
372  // scale
373  physicsTransform.setScale(body->transformScale);
374  // translation
375  physicsTransform.setTranslation(Vector3(transformPosition.x, transformPosition.y, transformPosition.z));
376  // done
377  physicsTransform.update();
378  }
379 }
380 
382 {
383  for (auto i = 0; i < rigidBodiesDynamic.size(); i++) {
384  // update rigid body
385  auto body = rigidBodiesDynamic[i];
386 
387  // skip on sleeping objects
388  if (body->isSleeping() == true) continue;
389 
390  // synch with engine entity
391  auto entity = engine->getEntity(body->getId());
392  if (entity == nullptr) {
393  Console::println("World::entity '" + body->getId() + "' not found");
394  continue;
395  }
396 
397  // enable
398  entity->setEnabled(body->isEnabled());
399 
400  // apply transform to engine entity
401  if (body->isEnabled() == true) entity->setTransform(body->transform);
402  }
403 }
404 
405 Body* World::determineHeight(uint16_t collisionTypeIds, float stepUpMax, const Vector3& point, Vector3& heightPoint, float minHeight, float maxHeight)
406 {
407  // TODO: we seem to have a bug here
408  //
409  class CustomCallbackClass : public reactphysics3d::RaycastCallback {
410  public:
411  CustomCallbackClass(float stepUpMax, const Vector3& point, float height = 10000.0f): stepUpMax(stepUpMax), point(point), height(height), body(nullptr) {
412  }
413  virtual reactphysics3d::decimal notifyRaycastHit(const reactphysics3d::RaycastInfo& info) {
414  Vector3 hitPoint(info.worldPoint.x, info.worldPoint.y, info.worldPoint.z);
415  auto _body = static_cast<Body*>(info.body->getUserData());
416  if (hitPoint.getY() < height && hitPoint.getY() <= point.getY() + stepUpMax) {
417  height = hitPoint.getY();
418  body = static_cast<Body*>(info.body->getUserData());
419  }
420  return reactphysics3d::decimal(info.hitFraction);
421  };
422  Body* getBody() {
423  return body;
424  }
425  float getHeight() {
426  return height;
427  }
428  private:
429  float stepUpMax;
430  Vector3 point;
431  float height;
432  Body* body;
433  };
434  reactphysics3d::Vector3 startPoint(point.getX(), maxHeight, point.getZ());
435  reactphysics3d::Vector3 endPoint(point.getX(), minHeight, point.getZ());
436  reactphysics3d::Ray ray(startPoint, endPoint);
437  CustomCallbackClass customCallbackObject(stepUpMax, point, maxHeight);
438  world->raycast(ray, &customCallbackObject, collisionTypeIds);
439  if (customCallbackObject.getBody() != nullptr) {
440  heightPoint.set(point);
441  heightPoint.setY(customCallbackObject.getHeight());
442  //
443  return customCallbackObject.getBody();
444  } else {
445  return nullptr;
446  }
447 }
448 
449 Body* World::doRayCasting(uint16_t collisionTypeIds, const Vector3& start, const Vector3& end, Vector3& hitPoint, const string& actorId)
450 {
451  class CustomCallbackClass : public reactphysics3d::RaycastCallback {
452  public:
453  CustomCallbackClass(const string& actorId): actorId(actorId), body(nullptr) {
454  }
455  virtual reactphysics3d::decimal notifyRaycastHit(const reactphysics3d::RaycastInfo& info) {
456  auto _body = static_cast<Body*>(info.body->getUserData());
457  if (actorId.size() == 0 || _body->getId() != actorId) {
458  body = _body;
459  hitPoint.set(info.worldPoint.x, info.worldPoint.y, info.worldPoint.z);
460  return reactphysics3d::decimal(info.hitFraction);
461  } else {
462  return reactphysics3d::decimal(1.0);
463  }
464  };
465  Body* getBody() {
466  return body;
467  }
468  const Vector3& getHitPoint() {
469  return hitPoint;
470  }
471  private:
472  string actorId;
473  Vector3 hitPoint;
474  Body* body;
475  };
476  reactphysics3d::Vector3 startPoint(start.getX(), start.getY(), start.getZ());
477  reactphysics3d::Vector3 endPoint(end.getX(), end.getY(), end.getZ());
478  reactphysics3d::Ray ray(startPoint, endPoint);
479  CustomCallbackClass customCallbackObject(actorId);
480  world->raycast(ray, &customCallbackObject, collisionTypeIds);
481  if (customCallbackObject.getBody() != nullptr) {
482  hitPoint.set(customCallbackObject.getHitPoint());
483  return customCallbackObject.getBody();
484  } else {
485  return nullptr;
486  }
487 }
488 
489 bool World::doesCollideWith(uint16_t collisionTypeIds, Body* body, vector<Body*>& collisionBodies) {
490  // callback
491  class CustomOverlapCallback: public reactphysics3d::OverlapCallback {
492  public:
493  CustomOverlapCallback(int collisionTypeIds, Body* body, vector<Body*>& collisionBodies): collisionTypeIds(collisionTypeIds), body(body), collisionBodies(collisionBodies) {
494  }
495 
496  void onOverlap(CallbackData &callbackData) {
497  for (auto i = 0; i < callbackData.getNbOverlappingPairs(); i++) {
498  auto overlappingPair = callbackData.getOverlappingPair(i);
499  auto body1 = static_cast<Body*>(overlappingPair.getBody1()->getUserData());
500  auto body2 = static_cast<Body*>(overlappingPair.getBody2()->getUserData());
501  if (body != body1 && ((body1->getCollisionTypeId() & collisionTypeIds) != 0)) collisionBodies.push_back(body1);
502  if (body != body2 && ((body2->getCollisionTypeId() & collisionTypeIds) != 0)) collisionBodies.push_back(body2);
503  }
504  }
505  private:
506  int collisionTypeIds;
507  Body* body;
508  vector<Body*>& collisionBodies;
509  };
510 
511  // do the test
512  CustomOverlapCallback customOverlapCallback(collisionTypeIds, body, collisionBodies);
513  world->testOverlap(body->rigidBody, customOverlapCallback);
514 
515  // done
516  return collisionBodies.size() > 0;
517 }
518 
519 bool World::doesCollideWith(uint16_t collisionTypeIds, const Transform& transform, vector<BoundingVolume*> boundingVolumes, vector<Body*>& collisionBodies) {
520  auto collisionBody = addStaticCollisionBody("tdme.world->doescollidewith", 32768, true, transform, boundingVolumes);
521  doesCollideWith(collisionTypeIds, collisionBody, collisionBodies);
522  removeBody("tdme.world->doescollidewith");
523  return collisionBodies.size() > 0;
524 }
525 
526 bool World::doCollide(Body* body1, Body* body2) {
527  return world->testOverlap(body1->rigidBody, body2->rigidBody);
528 }
529 
530 bool World::getCollisionResponse(Body* body1, Body* body2, CollisionResponse& collision) {
531  // callback
532  class CustomCollisionCallback: public reactphysics3d::CollisionCallback {
533  public:
534  CustomCollisionCallback(CollisionResponse& collision): collision(collision) {
535  }
536 
537  void onContact(const CallbackData &callbackData) {
538  for (auto i = 0; i < callbackData.getNbContactPairs(); i++) {
539  auto contactPair = callbackData.getContactPair(i);
540  auto body1 = contactPair.getBody1();
541  auto body2 = contactPair.getBody2();
542  auto collider1 = contactPair.getCollider1();
543  auto collider2 = contactPair.getCollider2();
544  for (auto j = 0; j < contactPair.getNbContactPoints(); j++) {
545  auto contactPoint = contactPair.getContactPoint(j);
546  // construct collision
547  auto entity = collision.addResponse(-contactPoint.getPenetrationDepth());
548  auto normal = contactPoint.getWorldNormal();
549  entity->setNormal(Vector3(normal.x, normal.y, normal.z));
550  auto collider1LocalToWorldTransform1 = collider1->getLocalToWorldTransform();
551  auto collider2LocalToWorldTransform2 = collider2->getLocalToWorldTransform();
552  const auto& localPoint1 = contactPoint.getLocalPointOnCollider1();
553  const auto& localPoint2 = contactPoint.getLocalPointOnCollider2();
554  auto worldPoint1 = collider1LocalToWorldTransform1 * localPoint1;
555  auto worldPoint2 = collider2LocalToWorldTransform2 * localPoint2;
556  entity->addHitPoint(Vector3(worldPoint1.x, worldPoint1.y, worldPoint1.z));
557  entity->addHitPoint(Vector3(worldPoint2.x, worldPoint2.y, worldPoint2.z));
558  }
559  }
560  }
561 
562  private:
563  CollisionResponse& collision;
564  };
565  // do the test
566  CustomCollisionCallback customCollisionCallback(collision);
567  world->testCollision(body1->rigidBody, body2->rigidBody, customCollisionCallback);
568  return collision.getEntityCount() > 0;
569 }
570 
571 World* World::clone(const string& id, uint16_t collisionTypeIds)
572 {
573  //
574  auto clonedWorld = new World(id);
575  for (auto body: bodies) {
576  // clone obv
577  Body* clonedBody = nullptr;
578  auto bodyType = body->getType();
579 
580  // test type
581  if ((body->getCollisionTypeId() & collisionTypeIds) == 0) continue;
582 
583  // clone rigid body
584  switch (bodyType) {
586  clonedBody = clonedWorld->addStaticRigidBody(body->id, body->getCollisionTypeId(), body->isEnabled(), body->transform, body->getFriction(), body->boundingVolumes);
587  break;
589  clonedBody = clonedWorld->addRigidBody(body->id, body->getCollisionTypeId(), body->isEnabled(), body->transform, body->getRestitution(), body->getFriction(), body->getMass(), body->inertiaTensor, body->boundingVolumes);
590  break;
592  clonedBody = clonedWorld->addStaticCollisionBody(body->id, body->getCollisionTypeId(), body->isEnabled(), body->transform, body->boundingVolumes);
593  break;
595  clonedBody = clonedWorld->addDynamicCollisionBody(body->id, body->getCollisionTypeId(), body->isEnabled(), body->transform, body->boundingVolumes);
596  break;
597  default:
598  Console::println("World::clone(): Unsupported type: " + to_string(bodyType));
599  continue;
600  }
601 
602  // synch additional properties
603  synchronize(clonedBody, body);
604  }
605 
606  //
607  return clonedWorld;
608 }
609 
610 void World::synchronize(Body* clonedBody, Body* body)
611 {
612  clonedBody->setCollisionTypeIds(body->getCollisionTypeIds());
613  clonedBody->setEnabled(body->isEnabled());
614  clonedBody->setMass(body->getMass());
615  clonedBody->setTransform(body->transform);
616  if (clonedBody->getType() == Body::BODYTYPE_DYNAMIC) {
617  clonedBody->setLinearVelocity(body->getLinearVelocity());
618  clonedBody->setAngularVelocity(body->getAngularVelocity());
619  }
620 }
621 
623 {
624  for (auto i = 0; i < rigidBodiesDynamic.size(); i++) {
625  auto body = rigidBodiesDynamic.at(i);
626  auto clonedBody = world->getBody(body->id);
627  if (clonedBody == nullptr) {
628  Console::println("Cloned world::entity '" + body->id + "' not found");
629  continue;
630  }
631  // synch rigid bodies
632  synchronize(clonedBody, body);
633  }
634 }
635 
637 {
638  worldListeners.push_back(listener);
639 }
640 
642 {
643  worldListeners.erase(remove(worldListeners.begin(), worldListeners.end(), listener), worldListeners.end());
644 }
Engine main class.
Definition: Engine.h:131
Entity * getEntity(const string &id)
Returns a entity by given id.
Definition: Engine.h:1175
Engine entity.
Definition: Entity.h:30
Rotation representation.
Definition: Rotation.h:18
static const Rotation fromQuaternion(const Quaternion &quaternion)
Returns rotation from a quaternion.
Definition: Rotation.h:142
Transform which contain scale, rotations and translation.
Definition: Transform.h:29
const Vector3 & getTranslation() const
Definition: Transform.h:56
Rigid body class.
Definition: Body.h:41
void setTransform(const Transform &transform)
Set transform.
Definition: Body.h:383
uint16_t getCollisionTypeIds()
Definition: Body.h:194
reactphysics3d::RigidBody * rigidBody
Definition: Body.h:81
void setMass(float mass)
Set up mass.
Definition: Body.h:299
void setAngularVelocity(const Vector3 &angularVelocity)
Set angular velocity.
Definition: Body.h:338
void setEnabled(bool enabled)
Set up if rigid body is enabled.
Definition: Body.h:215
void setLinearVelocity(const Vector3 &linearVelocity)
Set linear velocity.
Definition: Body.h:319
const Transform & getTransform()
Definition: Body.h:375
const Vector3 getAngularVelocity()
Definition: Body.h:326
void setCollisionTypeIds(uint16_t collisionTypeIds)
Set up collision type ids.
Definition: Body.cpp:120
BodyType getType()
Return type, see TYPE_*.
Definition: Body.h:174
static const Vector3 getNoRotationInertiaTensor()
Definition: Body.h:75
const Vector3 getLinearVelocity()
Definition: Body.h:307
void setNormal(const Vector3 &normal)
Set normal.
CollisionResponse_Entity * addResponse(float distance)
Adds a collision response entity.
Dynamic physics world class.
Definition: World.h:38
BodyHierarchy * getBodyHierarchy(const string &id)
Returns body hierarchy identified by id.
Definition: World.cpp:205
Body * doRayCasting(uint16_t collisionTypeIds, const Vector3 &start, const Vector3 &end, Vector3 &hitPoint, const string &actorId=string())
Do a ray cast from given start to given end point, if there is any body with given collision type in ...
Definition: World.cpp:449
bool doesCollideWith(uint16_t collisionTypeIds, Body *body, vector< Body * > &collisionBodies)
Check if world collides with given body.
Definition: World.cpp:489
bool doCollide(Body *body1, Body *body2)
Check if body 1 collides with body 2.
Definition: World.cpp:526
void removeBody(const string &id)
Removes body identified by id.
Definition: World.cpp:211
reactphysics3d::PhysicsCommon physicsCommon
Definition: World.h:53
map< string, reactphysics3d::Joint * > jointsById
Definition: World.h:59
map< string, Body * > bodiesById
Definition: World.h:58
bool getCollisionResponse(Body *body1, Body *body2, CollisionResponse &collision)
Get collision response.
Definition: World.cpp:530
void synchronize(Body *clonedBody, Body *body)
Synchronize cloned body from body.
Definition: World.cpp:610
void addWorldListener(WorldListener *listener)
Add a world listener.
Definition: World.cpp:636
map< string, BodyCollisionStruct > bodyCollisionsLastFrame
Definition: World.h:60
World * clone(const string &id, uint16_t collisionTypeIds=~0)
Clone this world.
Definition: World.cpp:571
Body * getBody(const string &id)
Returns body identified by id.
Definition: World.h:151
vector< Body * > rigidBodiesDynamic
Definition: World.h:57
void addFixedJoint(const string &id, Body *body1, Body *body2)
Add fixed joint.
Definition: World.cpp:226
Body * addStaticRigidBody(const string &id, uint16_t collisionTypeId, bool enabled, const Transform &transform, float friction, const vector< BoundingVolume * > &boundingVolumes, bool hierarchy=false)
Add a static rigid body.
Definition: World.cpp:181
vector< WorldListener * > worldListeners
Definition: World.h:61
Body * addStaticCollisionBody(const string &id, uint16_t collisionTypeId, bool enabled, const Transform &transform, const vector< BoundingVolume * > &boundingVolumes, bool hierarchy=false)
Add a static collision body.
Definition: World.cpp:135
void removeJoint(const string &id)
Remove joint.
Definition: World.cpp:242
reactphysics3d::PhysicsWorld * world
Definition: World.h:54
Body * determineHeight(uint16_t collisionTypeIds, float stepUpMax, const Vector3 &point, Vector3 &heightPoint, float minHeight=-10000.0f, float maxHeight=10000.0f)
Determine height on x,y,u while respecting step up max.
Definition: World.cpp:405
void removeWorldListener(WorldListener *listener)
Remove a world listener.
Definition: World.cpp:641
void update(float deltaTime)
Update world.
Definition: World.cpp:251
void reset()
Resets the physic world.
Definition: World.cpp:94
Body * addRigidBody(const string &id, uint16_t collisionTypeId, bool enabled, const Transform &transform, float restitution, float friction, float mass, const Vector3 &inertiaTensor, const vector< BoundingVolume * > &boundingVolumes, bool hierarchy=false)
Add a rigid body.
Definition: World.cpp:110
Body * addDynamicCollisionBody(const string &id, uint16_t collisionTypeId, bool enabled, const Transform &transform, const vector< BoundingVolume * > &boundingVolumes, bool hierarchy=false)
Add a dynamic collision body.
Definition: World.cpp:158
vector< Body * > bodies
Definition: World.h:56
World(const string &id)
Public constructor.
Definition: World.cpp:76
Axis aligned bounding box used for frustum, this is not directly connectable with physics engine.
Definition: BoundingBox.h:26
Line segment helper functions.
Definition: LineSegment.h:16
Oriented bounding box physics primitive.
Standard math functions.
Definition: Math.h:19
Matrix4x4 class representing matrix4x4 mathematical structure and operations for 3d space.
Definition: Matrix4x4.h:23
Quaternion class representing quaternion mathematical structure and operations with x,...
Definition: Quaternion.h:24
Vector3 class representing vector3 mathematical structure and operations with x, y,...
Definition: Vector3.h:20
float getY() const
Definition: Vector3.h:117
float getX() const
Definition: Vector3.h:100
float getZ() const
Definition: Vector3.h:134
Vector3 & add(float scalar)
Adds a scalar.
Definition: Vector3.h:153
Vector3 & setY(float y)
Sets y component.
Definition: Vector3.h:126
Vector3 clone() const
Clones this vector3.
Definition: Vector3.h:374
Vector3 & scale(float scalar)
Scales by scalar.
Definition: Vector3.h:201
Vector3 & set(float x, float y, float z)
Sets this vector3 by its components.
Definition: Vector3.h:70
Console class.
Definition: Console.h:29
String tools class.
Definition: StringTools.h:22
Time utility class.
Definition: Time.h:20
World listener which is about notifying adding or removing bodies.
Definition: WorldListener.h:23