TDME2  1.9.200
Body.cpp
Go to the documentation of this file.
1 #include <string>
2 #include <vector>
3 
4 #include <reactphysics3d/body/RigidBody.h>
5 #include <reactphysics3d/collision/narrowphase/CollisionDispatch.h>
6 #include <reactphysics3d/collision/narrowphase/NarrowPhaseAlgorithm.h>
7 #include <reactphysics3d/collision/shapes/CollisionShape.h>
8 #include <reactphysics3d/collision/Collider.h>
9 #include <reactphysics3d/collision/CollisionCallback.h>
10 #include <reactphysics3d/constraint/ContactPoint.h>
11 #include <reactphysics3d/engine/PhysicsWorld.h>
12 #include <reactphysics3d/mathematics/Quaternion.h>
13 #include <reactphysics3d/mathematics/Transform.h>
14 #include <reactphysics3d/mathematics/Vector3.h>
15 #include <reactphysics3d/memory/MemoryAllocator.h>
16 
17 #include <tdme/tdme.h>
24 #include <tdme/engine/Rotation.h>
25 #include <tdme/engine/Transform.h>
26 #include <tdme/math/Math.h>
27 #include <tdme/math/Matrix4x4.h>
28 #include <tdme/math/Quaternion.h>
29 #include <tdme/math/Vector3.h>
30 #include <tdme/utilities/Console.h>
31 
32 using std::string;
33 using std::to_string;
34 using std::vector;
35 
44 using tdme::math::Math;
49 
50 Body::Body(World* world, const string& id, BodyType type, uint16_t collisionTypeId, bool enabled, const Transform& transform, float restitution, float friction, float mass, const Vector3& inertiaTensor, const vector<BoundingVolume*>& boundingVolumes)
51 {
52  this->world = world;
53  this->id = id;
54  this->inertiaTensor = inertiaTensor;
55  this->type = type;
56  this->restitution = restitution;
57  this->friction = friction;
58  this->mass = mass;
59  this->collisionTypeIds = ~0;
60  this->collisionTypeId = collisionTypeId;
61  this->initiation = true;
62  //
63  switch (type) {
64  case BODYTYPE_STATIC:
66  rigidBody = this->world->world->createRigidBody(reactphysics3d::Transform());
67  rigidBody->setType(reactphysics3d::BodyType::STATIC);
68  rigidBody->setMass(mass);
69  rigidBody->setIsAllowedToSleep(true);
70  rigidBody->enableGravity(false);
71  rigidBody->setIsSleeping(true);
72  break;
73  case BODYTYPE_DYNAMIC:
75  rigidBody = this->world->world->createRigidBody(reactphysics3d::Transform());
76  rigidBody->setType(reactphysics3d::BodyType::DYNAMIC);
77  rigidBody->setMass(mass);
78  rigidBody->setIsAllowedToSleep(true);
79  if (type == BODYTYPE_DYNAMIC) rigidBody->enableGravity(true);
80  break;
81  case BODYTYPE_KINEMATIC:
82  rigidBody = this->world->world->createRigidBody(reactphysics3d::Transform());
83  rigidBody->setType(reactphysics3d::BodyType::KINEMATIC);
84  rigidBody->setMass(mass);
85  rigidBody->setIsAllowedToSleep(true);
86  break;
87  default:
88  Console::println("Body::Body(): unsupported type: " + to_string(type) + ": using collision body");
89  break;
90  }
91  rigidBody->setUserData(this);
92  // clone bounding volumes
93  for (auto boundingVolume: boundingVolumes) {
94  this->boundingVolumes.push_back(boundingVolume->clone());
95  }
96  // finally create collision shapes
97  for (auto boundingVolume: this->boundingVolumes) {
98  boundingVolume->createCollisionShape(world);
99  }
100  //
102  setEnabled(enabled);
103 }
104 
106  // remove colliders
108  // destroy rigid body
109  this->world->world->destroyRigidBody(rigidBody);
110 }
111 
112 void Body::setCollisionTypeId(uint16_t typeId)
113 {
114  this->collisionTypeId = typeId;
115  for (auto collider: colliders) {
116  collider->setCollisionCategoryBits(typeId);
117  }
118 }
119 
120 void Body::setCollisionTypeIds(uint16_t collisionTypeIds)
121 {
122  this->collisionTypeIds = collisionTypeIds;
123  for (auto collider: colliders) {
124  collider->setCollideWithMaskBits(collisionTypeIds);
125  }
126 }
127 
129  // we need the scale from our body transform to be passed as local transform when resetting colliders
130  Transform scaleTransform;
131  scaleTransform.setScale(transform.getScale());
132  scaleTransform.update();
133  // reset colliders, means remove and add them and create colliders with correct scale
134  resetColliders(colliders, boundingVolumes, scaleTransform);
135  // set up inverse inertia tensor local
136  if (type == BODYTYPE_DYNAMIC) rigidBody->setLocalInertiaTensor(reactphysics3d::Vector3(inertiaTensor.getX(), inertiaTensor.getY(), inertiaTensor.getZ()));
137 }
138 
139 void Body::removeColliders(vector<reactphysics3d::Collider*>& colliders, vector<BoundingVolume*>& boundingVolumes) {
140  // remove colliders
141  for (auto collider: colliders) {
142  rigidBody->removeCollider(collider);
143  }
144  colliders.clear();
145  // delete bounding volumes
146  for (auto boundingVolume: boundingVolumes) {
147  delete boundingVolume;
148  }
149  boundingVolumes.clear();
150 }
151 
152 void Body::resetColliders(vector<reactphysics3d::Collider*>& colliders, vector<BoundingVolume*>& boundingVolumes, const Transform& localTransform) {
153  // remove colliders
154  for (auto collider: colliders) rigidBody->removeCollider(collider);
155  colliders.clear();
156 
157  // set up scale
158  for (auto boundingVolume: boundingVolumes) {
159  // scale bounding volume and recreate it if nessessary
160  if (boundingVolume->getScale().equals(localTransform.getScale()) == false) {
161  boundingVolume->destroyCollisionShape();
162  boundingVolume->setScale(localTransform.getScale());
163  boundingVolume->createCollisionShape(world);
164  }
165  }
166 
167  // determine total volume
168  /*
169  float volumeTotal = 0.0f;
170  for (auto boundingVolume: boundingVolumes) {
171  // skip if not attached
172  if (boundingVolume->isAttachedToWorld() == false) continue;
173  //
174  volumeTotal+=
175  boundingVolume->worldBoundingBox.getDimensions().getX() *
176  boundingVolume->worldBoundingBox.getDimensions().getY() *
177  boundingVolume->worldBoundingBox.getDimensions().getZ();
178  }
179  */
180 
181  // add bounding volumes with mass
182  for (auto boundingVolume: boundingVolumes) {
183  // skip if not attached
184  if (boundingVolume->isAttachedToWorld() == false) continue;
185  //
186  /*
187  float volumeBoundingVolume =
188  boundingVolume->worldBoundingBox.getDimensions().getX() *
189  boundingVolume->worldBoundingBox.getDimensions().getY() *
190  boundingVolume->worldBoundingBox.getDimensions().getZ();
191  */
192  //
193  reactphysics3d::Transform localTransformRP3D(
194  reactphysics3d::Vector3(localTransform.getTranslation().getX(), localTransform.getTranslation().getY(), localTransform.getTranslation().getZ()),
195  reactphysics3d::Quaternion(localTransform.getRotationsQuaternion().getX(), localTransform.getRotationsQuaternion().getY(), localTransform.getRotationsQuaternion().getZ(), localTransform.getRotationsQuaternion().getW())
196  );
197 
198  //
199  auto collider = rigidBody->addCollider(boundingVolume->collisionShape, localTransformRP3D * boundingVolume->collisionShapeLocalTransform);
200  collider->getMaterial().setBounciness(restitution);
201  collider->getMaterial().setFrictionCoefficient(friction);
202  if (type == BODYTYPE_COLLISION_STATIC || type == BODYTYPE_COLLISION_DYNAMIC) collider->setIsTrigger(true);
203  // collider->getMaterial().setMassDensity(volumeBoundingVolume / volumeTotal);
204 
205  //
206  collider->setCollideWithMaskBits(collisionTypeIds);
207  collider->setCollisionCategoryBits(collisionTypeId);
208 
209  //
210  colliders.push_back(collider);
211  }
212  // seems to be a bug here, I have no idea why I have to set here a identity transform
213  rigidBody->setTransform(reactphysics3d::Transform());
214  // set inverse inertia tensor local
215  rigidBody->setLocalInertiaTensor(reactphysics3d::Vector3(inertiaTensor.getX(), inertiaTensor.getY(), inertiaTensor.getZ()));
216 }
217 
218 void Body::setFriction(float friction)
219 {
220  //
221  this->friction = friction;
222  for(auto collider: colliders) collider->getMaterial().setFrictionCoefficient(friction);
223 }
224 
225 void Body::setRestitution(float restitution)
226 {
227  //
228  this->restitution = restitution;
229  for(auto collider: colliders) collider->getMaterial().setBounciness(restitution);
230 }
231 
233 {
234  collisionListener.push_back(listener);
235 }
236 
238 {
239  collisionListener.erase(remove(collisionListener.begin(), collisionListener.end(), listener), collisionListener.end());
240 }
241 
242 void Body::fireOnCollision(Body* other, CollisionResponse& collisionResponse)
243 {
244  for (auto listener: collisionListener) {
245  listener->onCollision(this, other, collisionResponse);
246  }
247 }
248 
249 void Body::fireOnCollisionBegin(Body* other, CollisionResponse& collisionResponse)
250 {
251  for (auto listener: collisionListener) {
252  listener->onCollisionBegin(this, other, collisionResponse);
253  }
254 }
255 
257 {
258  for (auto listener: collisionListener) {
259  listener->onCollisionEnd(this, other);
260  }
261 }
Rotation representation.
Definition: Rotation.h:18
Transform which contain scale, rotations and translation.
Definition: Transform.h:29
const Vector3 & getScale() const
Definition: Transform.h:71
void setScale(const Vector3 &scale)
Set scale.
Definition: Transform.h:79
const Quaternion & getRotationsQuaternion() const
Definition: Transform.h:162
virtual void update()
Computes transform matrix.
Definition: Transform.cpp:33
const Vector3 & getTranslation() const
Definition: Transform.h:56
Rigid body class.
Definition: Body.h:41
vector< BoundingVolume * > boundingVolumes
Definition: Body.h:92
void setTransform(const Transform &transform)
Set transform.
Definition: Body.h:383
vector< CollisionListener * > collisionListener
Definition: Body.h:94
reactphysics3d::RigidBody * rigidBody
Definition: Body.h:81
void fireOnCollisionBegin(Body *other, CollisionResponse &collisionResponse)
Fire on collision begin.
Definition: Body.cpp:249
void removeColliders(vector< reactphysics3d::Collider * > &colliders, vector< BoundingVolume * > &boundingVolumes)
Remove colliders.
Definition: Body.cpp:139
void setEnabled(bool enabled)
Set up if rigid body is enabled.
Definition: Body.h:215
void setFriction(float friction)
Set up friction.
Definition: Body.cpp:218
void setRestitution(float restitution)
Set up restitution.
Definition: Body.cpp:225
void setCollisionTypeId(uint16_t typeId)
Set collision type id.
Definition: Body.cpp:112
void removeCollisionListener(CollisionListener *listener)
Remove a collision listener to this rigid body.
Definition: Body.cpp:237
void fireOnCollisionEnd(Body *other)
Fire on collision end.
Definition: Body.cpp:256
uint16_t collisionTypeIds
Definition: Body.h:87
virtual ~Body()
Destructor.
Definition: Body.cpp:105
virtual void resetColliders()
Reset body colliders.
Definition: Body.cpp:128
void setCollisionTypeIds(uint16_t collisionTypeIds)
Set up collision type ids.
Definition: Body.cpp:120
uint16_t collisionTypeId
Definition: Body.h:88
void addCollisionListener(CollisionListener *listener)
Add a collision listener to this rigid body.
Definition: Body.cpp:232
vector< reactphysics3d::Collider * > colliders
Definition: Body.h:93
void fireOnCollision(Body *other, CollisionResponse &collisionResponse)
Fire on collision.
Definition: Body.cpp:242
Dynamic physics world class.
Definition: World.h:38
reactphysics3d::PhysicsWorld * world
Definition: World.h:54
Axis aligned bounding box used for frustum, this is not directly connectable with physics engine.
Definition: BoundingBox.h:26
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
float getY() const
Definition: Quaternion.h:174
float getX() const
Definition: Quaternion.h:157
float getZ() const
Definition: Quaternion.h:191
float getW() const
Definition: Quaternion.h:208
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
Console class.
Definition: Console.h:29