Leviathan  0.8.0.0
Leviathan game engine
Leviathan::PhysicalWorld Class Reference

#include <PhysicalWorld.h>

Public Member Functions

DLLEXPORT PhysicalWorld (GameWorld *owner, PhysicsMaterialManager *physicscallbacks)
 
DLLEXPORT ~PhysicalWorld ()
 
DLLEXPORT void SimulateWorld (float secondspassed, int maxsubsteps=8)
 Advances the simulation the specified amount of time. More...
 
DLLEXPORT PhysicsShape::pointer CreateCompound ()
 
DLLEXPORT PhysicsShape::pointer CreateSphere (float radius)
 
DLLEXPORT PhysicsShape::pointer CreateBox (float xdimension, float ydimension, float zdimension)
 The dimensions are halfwidths of the box along each axis. More...
 
DLLEXPORT PhysicsShape::pointer CreateCone (float radius, float height)
 
DLLEXPORT PhysicsConstraint::pointer CreateFixedConstraint (const PhysicsBody::pointer &a, const PhysicsBody::pointer &b, const Float3 &aoffset, const Quaternion &aorientation, const Float3 &boffset, const Quaternion &borientation)
 
DLLEXPORT bool DestroyConstraint (PhysicsConstraint *constraint)
 Destroys a physics constraint. More...
 
DLLEXPORT PhysicsBody::pointer CreateBodyFromCollision (const PhysicsShape::pointer &shape, float mass, PhysicsPositionProvider *positionsynchronization, int physicsmaterialid=-1)
 Constraints body to a 2d plane of movement specified by its normal. More...
 
DLLEXPORT bool ChangeBodyShape (const PhysicsBody::pointer &body, const PhysicsShape::pointer &shape)
 Applies a changed shape to a body. More...
 
DLLEXPORT bool DestroyBody (PhysicsBody *body)
 Destroys a physics body. More...
 
const PhysMaterialDataPairGetMaterialPair (int id1, int id2) const
 Finds the information for contact between objects with two materials. More...
 
DLLEXPORT void SetDebugDrawer (const std::shared_ptr< PhysicsDebugDrawer > &drawer)
 Sets or clears the debug drawer used by this world. More...
 
DLLEXPORT GameWorldGetGameWorld ()
 
PhysicsShapeCreateSphereWrapper (float radius)
 
PhysicsShapeCreateConeWrapper (float radius, float height)
 
PhysicsShapeCreateCompoundWrapper ()
 
PhysicsConstraintCreateFixedConstraintWrapper (PhysicsBody *a, PhysicsBody *b, const Float3 &aoffset, const Quaternion &aorientation, const Float3 &boffset, const Quaternion &borientation)
 
bool DestroyConstraintWrapper (PhysicsConstraint *constraint)
 

Protected Member Functions

void OnManifoldWithContact (btPersistentManifold *contactManifold, const btManifoldPoint &contactPoint, const PhysMaterialDataPair &pair, PhysicsBody *body1, PhysicsBody *body2)
 Calls appropriate material callbacks. This is called once per contact manifold that has penetrating points. More...
 

Static Protected Member Functions

static void OnPhysicsSubStep (btDynamicsWorld *world, btScalar timeStep)
 

Protected Attributes

float PassedTimeTotal = 0
 Total amount of seconds required to be simulated. More...
 
GameWorldOwningWorld
 
PhysicsMaterialManagerPhysicsMaterials
 
bool PhysicsUpdateInProgress = false
 This is a small sanity check for preventing destroying physics bodies during a tick. More...
 
std::unique_ptr< btDefaultCollisionConfiguration > CollisionConfiguration
 
std::unique_ptr< btCollisionDispatcher > Dispatcher
 
std::unique_ptr< btBroadphaseInterface > OverlappingPairCache
 
std::unique_ptr< btSequentialImpulseConstraintSolver > Solver
 
std::unique_ptr< btDiscreteDynamicsWorld > DynamicsWorld
 
std::unique_ptr< LeviathanPhysicsOverlapFilterOverlapFilter
 
std::vector< PhysicsBody::pointer > PhysicsBodies
 We need to keep the physic bodies alive (guaranteed) until they are destroyed. More...
 
std::vector< PhysicsConstraint::pointer > PhysicsConstraints
 We need to keep constraints alive until they are destroyed. More...
 
std::shared_ptr< PhysicsDebugDrawerDebugDrawer
 

Detailed Description

Definition at line 56 of file PhysicalWorld.h.

Constructor & Destructor Documentation

◆ PhysicalWorld()

DLLEXPORT PhysicalWorld::PhysicalWorld ( GameWorld owner,
PhysicsMaterialManager physicscallbacks 
)

Definition at line 77 of file PhysicalWorld.cpp.

78  :
79  OwningWorld(owner),
80  PhysicsMaterials(physicscallbacks),
81  OverlapFilter(std::make_unique<LeviathanPhysicsOverlapFilter>(this))
82 {
83  // Setup physics world //
84  CollisionConfiguration = std::make_unique<btDefaultCollisionConfiguration>();
85 
86  // Non-parallel dispatcher
87  Dispatcher = std::make_unique<btCollisionDispatcher>(CollisionConfiguration.get());
88 
89  // According to docs this is a good general broadphase
90  OverlappingPairCache = std::make_unique<btDbvtBroadphase>();
91 
92  // Non-parallel solver
93  Solver = std::make_unique<btSequentialImpulseConstraintSolver>();
94 
95  DynamicsWorld = std::make_unique<btDiscreteDynamicsWorld>(Dispatcher.get(),
97 
98  // Register required callbacks
99  DynamicsWorld->setInternalTickCallback(&PhysicalWorld::OnPhysicsSubStep);
100  // Not sure which one of these is better to use for AABB overlap
101  DynamicsWorld->getPairCache()->setOverlapFilterCallback(OverlapFilter.get());
102  // Dispatcher->setNearCallback(&PhysicalWorld::PhysicsNearCallback);
103 
104  // Set gravity. Having this set on worlds that want multiple different gravities might be
105  // an issue
106  DynamicsWorld->setGravity(btVector3(0, PHYSICS_BASE_GRAVITY, 0));
107 
108  // Set us as the user data (this is done last so that nothing overwrites this) //
109  DynamicsWorld->setWorldUserInfo(this);
110 
111  LEVIATHAN_ASSERT(DynamicsWorld->getWorldUserInfo() != nullptr, "userinfo set failed");
112 }
constexpr auto PHYSICS_BASE_GRAVITY
Definition: PhysicalWorld.h:40
std::unique_ptr< btDefaultCollisionConfiguration > CollisionConfiguration
std::unique_ptr< btBroadphaseInterface > OverlappingPairCache
std::unique_ptr< btCollisionDispatcher > Dispatcher
static void OnPhysicsSubStep(btDynamicsWorld *world, btScalar timeStep)
PhysicsMaterialManager * PhysicsMaterials
#define LEVIATHAN_ASSERT(x, msg)
Definition: Define.h:100
std::unique_ptr< LeviathanPhysicsOverlapFilter > OverlapFilter
std::unique_ptr< btDiscreteDynamicsWorld > DynamicsWorld
std::unique_ptr< btSequentialImpulseConstraintSolver > Solver

◆ ~PhysicalWorld()

DLLEXPORT PhysicalWorld::~PhysicalWorld ( )

Definition at line 114 of file PhysicalWorld.cpp.

115 {
116  // It is an error to not release a body
117  if(!PhysicsBodies.empty()) {
118  LOG_ERROR("PhysicalWorld: not all bodies have been destroyed, alive count: " +
119  std::to_string(PhysicsBodies.size()));
120  }
121 
122  // All bodies need to be destroyed here
123  while(!PhysicsBodies.empty()) {
124  DestroyBody(PhysicsBodies.back().get());
125  }
126 
127  // We can rely on the default delete order and everything is fine
128 }
std::vector< PhysicsBody::pointer > PhysicsBodies
We need to keep the physic bodies alive (guaranteed) until they are destroyed.
#define LOG_ERROR(x)
Definition: Define.h:92
DLLEXPORT bool DestroyBody(PhysicsBody *body)
Destroys a physics body.

Member Function Documentation

◆ ChangeBodyShape()

DLLEXPORT bool PhysicalWorld::ChangeBodyShape ( const PhysicsBody::pointer &  body,
const PhysicsShape::pointer &  shape 
)

Applies a changed shape to a body.

Todo:
Find out if it is required to remove and add the body back to the world (and if that can be done in a physics callback)

Definition at line 443 of file PhysicalWorld.cpp.

445 {
446  if(!body || !shape || !body->GetBody())
447  return false;
448 
449  // Debug safety code
450  bool found = false;
451  for(auto iter = PhysicsBodies.begin(); iter != PhysicsBodies.end(); ++iter) {
452  if(iter->get() == body.get()) {
453 
454  found = true;
455  break;
456  }
457  }
458 
459  if(!found) {
460  LOG_ERROR("PhysicalWorld: ChangeBodyShape: passed body not part of this world");
461  DEBUG_BREAK;
462  return false;
463  }
464 
465  // This might be fine as it will be added back in
466  if(body->GetBody()->getNumConstraintRefs() > 0) {
467  // "undestroyed constraints on entity";
468  }
469 
471  // This might be okay...
472  // DEBUG_BREAK;
473  }
474 
475  DynamicsWorld->removeRigidBody(body->GetBody());
476 
477  body->ApplyShapeChange(shape);
478 
479  DynamicsWorld->addRigidBody(body->GetBody());
480 
481  return true;
482 }
std::vector< PhysicsBody::pointer > PhysicsBodies
We need to keep the physic bodies alive (guaranteed) until they are destroyed.
bool PhysicsUpdateInProgress
This is a small sanity check for preventing destroying physics bodies during a tick.
#define LOG_ERROR(x)
Definition: Define.h:92
std::unique_ptr< btDiscreteDynamicsWorld > DynamicsWorld

◆ CreateBodyFromCollision()

DLLEXPORT PhysicsBody::pointer PhysicalWorld::CreateBodyFromCollision ( const PhysicsShape::pointer &  shape,
float  mass,
PhysicsPositionProvider positionsynchronization,
int  physicsmaterialid = -1 
)

Constraints body to a 2d plane of movement specified by its normal.

Note
DestroyBody must be called to remove the created body from this world
Parameters
massIf 0 then this is a static body

Definition at line 368 of file PhysicalWorld.cpp.

371 {
372  if(!shape)
373  return nullptr;
374 
375  btTransform transform;
376  transform.setIdentity();
377 
378  if(positionsynchronization) {
379  const Float3* position;
380  const Quaternion* orientation;
381  positionsynchronization->GetPositionDataForPhysics(position, orientation);
382 
383  transform.setRotation(*orientation);
384  transform.setOrigin(*position);
385  }
386 
387  // rigidbody is dynamic if and only if mass is non zero, otherwise static
388  const bool isDynamic = mass > 0;
389 
390  btVector3 localInertia(0, 0, 0);
391  if(isDynamic)
392  shape->GetShape()->calculateLocalInertia(mass, localInertia);
393 
394  // To not have to lookup all positions all the time we use the position synchronization
395  // object
396  std::unique_ptr<PhysicsDataBridge> positionBridge;
397 
398  if(positionsynchronization)
399  positionBridge = std::make_unique<PhysicsDataBridge>(positionsynchronization);
400 
401  btRigidBody::btRigidBodyConstructionInfo info(
402  mass, positionBridge.get(), shape->GetShape(), localInertia);
403 
404  auto body = PhysicsBody::MakeShared<PhysicsBody>(std::make_unique<btRigidBody>(info), mass,
405  shape, std::move(positionBridge), physicsmaterialid);
406 
407  if(!body->GetBody()) {
408  LOG_ERROR("PhysicalWorld: CreateBodyFromCollision: failed to create bullet body");
409  return nullptr;
410  }
411 
412  // Apply material
413  if(physicsmaterialid != -1 && PhysicsMaterials) {
414  auto material = PhysicsMaterials->GetMaterial(physicsmaterialid);
415 
416  if(!material) {
417  LOG_ERROR(
418  "PhysicalWorld: CreateBodyFromCollision: can't find physics material id: " +
419  std::to_string(physicsmaterialid));
420  body->SetPhysicalMaterialID(-1);
421  } else {
422 
423  body->ApplyMaterial(*material);
424  }
425  }
426 
427  // Dirty hack to make bodies not sleep. This makes apply force work (another approach would
428  // be to wake any body that has force applied to it)
429  body->GetBody()->setActivationState(DISABLE_DEACTIVATION);
430 
432  // This might be okay...
433  // DEBUG_BREAK;
434  }
435 
436  DynamicsWorld->addRigidBody(body->GetBody());
437 
438  // Make sure it is alive as long as it is in the world
439  PhysicsBodies.push_back(body);
440  return body;
441 }
std::vector< PhysicsBody::pointer > PhysicsBodies
We need to keep the physic bodies alive (guaranteed) until they are destroyed.
bool PhysicsUpdateInProgress
This is a small sanity check for preventing destroying physics bodies during a tick.
#define LOG_ERROR(x)
Definition: Define.h:92
virtual void GetPositionDataForPhysics(const Float3 *&position, const Quaternion *&orientation) const =0
PhysicsMaterialManager * PhysicsMaterials
DLLEXPORT PhysicalMaterial * GetMaterial(const std::string &name)
Accesses material based on name.
A Quaternion type to make quaternion specific operations easier to access.
Definition: Quaternion.h:14
std::unique_ptr< btDiscreteDynamicsWorld > DynamicsWorld

◆ CreateBox()

DLLEXPORT PhysicsShape::pointer PhysicalWorld::CreateBox ( float  xdimension,
float  ydimension,
float  zdimension 
)

The dimensions are halfwidths of the box along each axis.

Definition at line 302 of file PhysicalWorld.cpp.

304 {
305  return PhysicsShape::MakeShared<PhysicsShape>(
306  std::make_unique<btBoxShape>(btVector3(xdimension, ydimension, zdimension)));
307 }

◆ CreateCompound()

DLLEXPORT PhysicsShape::pointer PhysicalWorld::CreateCompound ( )

Definition at line 284 of file PhysicalWorld.cpp.

285 {
286  return PhysicsShape::MakeShared<PhysicsShape>(std::make_unique<btCompoundShape>());
287 }

◆ CreateCompoundWrapper()

PhysicsShape* Leviathan::PhysicalWorld::CreateCompoundWrapper ( )
inline

Definition at line 139 of file PhysicalWorld.h.

140  {
141  return CreateCompound().detach();
142  }
DLLEXPORT PhysicsShape::pointer CreateCompound()

◆ CreateCone()

DLLEXPORT PhysicsShape::pointer PhysicalWorld::CreateCone ( float  radius,
float  height 
)

Definition at line 309 of file PhysicalWorld.cpp.

310 {
311  return PhysicsShape::MakeShared<PhysicsShape>(
312  std::make_unique<btConeShape>(radius, height));
313 }

◆ CreateConeWrapper()

PhysicsShape* Leviathan::PhysicalWorld::CreateConeWrapper ( float  radius,
float  height 
)
inline

Definition at line 134 of file PhysicalWorld.h.

135  {
136  return CreateCone(radius, height).detach();
137  }
DLLEXPORT PhysicsShape::pointer CreateCone(float radius, float height)

◆ CreateFixedConstraint()

DLLEXPORT PhysicsConstraint::pointer PhysicalWorld::CreateFixedConstraint ( const PhysicsBody::pointer &  a,
const PhysicsBody::pointer &  b,
const Float3 aoffset,
const Quaternion aorientation,
const Float3 boffset,
const Quaternion borientation 
)

Definition at line 315 of file PhysicalWorld.cpp.

318 {
319  if(!a || !a->GetBody() || !b || !b->GetBody())
320  return nullptr;
321 
322  btTransform aTransform;
323  aTransform.setIdentity();
324 
325  aTransform.setRotation(aorientation);
326  aTransform.setOrigin(aoffset);
327 
328  btTransform bTransform;
329  bTransform.setIdentity();
330 
331  bTransform.setRotation(borientation);
332  bTransform.setOrigin(boffset);
333 
334  auto newConstraint = PhysicsConstraint::MakeShared<PhysicsConstraint>(
335  new btFixedConstraint(*a->GetBody(), *b->GetBody(), aTransform, bTransform), a.get(),
336  b.get());
337 
338  DynamicsWorld->addConstraint(newConstraint->GetConstraint());
339  PhysicsConstraints.push_back(newConstraint);
340 
341  return newConstraint;
342 }
std::vector< PhysicsConstraint::pointer > PhysicsConstraints
We need to keep constraints alive until they are destroyed.
std::unique_ptr< btDiscreteDynamicsWorld > DynamicsWorld

◆ CreateFixedConstraintWrapper()

PhysicsConstraint* Leviathan::PhysicalWorld::CreateFixedConstraintWrapper ( PhysicsBody a,
PhysicsBody b,
const Float3 aoffset,
const Quaternion aorientation,
const Float3 boffset,
const Quaternion borientation 
)
inline

Definition at line 144 of file PhysicalWorld.h.

147  {
149  aorientation, boffset, borientation)
150  .detach();
151  }
DLLEXPORT PhysicsConstraint::pointer CreateFixedConstraint(const PhysicsBody::pointer &a, const PhysicsBody::pointer &b, const Float3 &aoffset, const Quaternion &aorientation, const Float3 &boffset, const Quaternion &borientation)
static boost::intrusive_ptr< ActualType > WrapPtr(ActualType *ptr)
Creates an intrusive_ptr from raw pointer.

◆ CreateSphere()

DLLEXPORT PhysicsShape::pointer PhysicalWorld::CreateSphere ( float  radius)

Definition at line 289 of file PhysicalWorld.cpp.

290 {
291 #ifdef CHECK_FOR_NANS
292  if(std::isnan(radius)) {
293 
294  DEBUG_BREAK;
295  throw std::runtime_error("CreateSphere has NaNs in it!");
296  }
297 #endif // CHECK_FOR_NANS
298 
299  return PhysicsShape::MakeShared<PhysicsShape>(std::make_unique<btSphereShape>(radius));
300 }
#define isnan(x)
Definition: jsoncpp.cpp:4243

◆ CreateSphereWrapper()

PhysicsShape* Leviathan::PhysicalWorld::CreateSphereWrapper ( float  radius)
inline

Definition at line 129 of file PhysicalWorld.h.

130  {
131  return CreateSphere(radius).detach();
132  }
DLLEXPORT PhysicsShape::pointer CreateSphere(float radius)

◆ DestroyBody()

DLLEXPORT bool PhysicalWorld::DestroyBody ( PhysicsBody body)

Destroys a physics body.

May not be called while a physics update is in progress

Definition at line 484 of file PhysicalWorld.cpp.

485 {
487  LOG_FATAL("PhysicalWorld: DestroyBody: called while physics update is in progress");
488  return false;
489  }
490 
491  // Remove from alive bodies. This also checks that the body is in this world
492  for(auto iter = PhysicsBodies.begin(); iter != PhysicsBodies.end(); ++iter) {
493 
494  if(iter->get() == body) {
495 
496  // Destroy all constraints we can see
497  while(!body->GetConstraints().empty()) {
498  DestroyConstraint(body->GetConstraints().front().get());
499  }
500 
501  if(body->GetBody()->getNumConstraintRefs() > 0) {
502 
503  LOG_ERROR("PhysicalWorld: DestroyBody: body has undestroyed constraints, "
504  "can't safely destroy");
505  return false;
506  }
507 
508  DynamicsWorld->removeRigidBody(body->GetBody());
509 
510  body->DetachResources();
511  PhysicsBodies.erase(iter);
512  return true;
513  }
514  }
515 
516  LOG_ERROR("PhysicalWorld: DestroyBody: called with body that wasn't in this world");
517  return false;
518 }
DLLEXPORT btRigidBody * GetBody()
Definition: PhysicsBody.h:167
DLLEXPORT const auto & GetConstraints() const
Definition: PhysicsBody.h:193
std::vector< PhysicsBody::pointer > PhysicsBodies
We need to keep the physic bodies alive (guaranteed) until they are destroyed.
bool PhysicsUpdateInProgress
This is a small sanity check for preventing destroying physics bodies during a tick.
#define LOG_ERROR(x)
Definition: Define.h:92
#define LOG_FATAL(x)
Definition: Define.h:94
DLLEXPORT void DetachResources()
This releases all resources held by this. This is called by the PhysicalWorld when this is destroyed ...
Definition: PhysicsBody.cpp:38
DLLEXPORT bool DestroyConstraint(PhysicsConstraint *constraint)
Destroys a physics constraint.
std::unique_ptr< btDiscreteDynamicsWorld > DynamicsWorld

◆ DestroyConstraint()

DLLEXPORT bool PhysicalWorld::DestroyConstraint ( PhysicsConstraint constraint)

Destroys a physics constraint.

May not be called while a physics update is in progress

Definition at line 344 of file PhysicalWorld.cpp.

345 {
347  LOG_FATAL(
348  "PhysicalWorld: DestroyConstraint: called while physics update is in progress");
349  return false;
350  }
351 
352  // Remove from existing constraints and the world
353  for(auto iter = PhysicsConstraints.begin(); iter != PhysicsConstraints.end(); ++iter) {
354  if(iter->get() == constraint) {
355 
356  DynamicsWorld->removeConstraint(constraint->GetConstraint());
357 
358  constraint->DetachResources();
359  PhysicsConstraints.erase(iter);
360  return true;
361  }
362  }
363 
364  // This is not serious as destroying bodies can trigger destroying constraints
365  return false;
366 }
bool PhysicsUpdateInProgress
This is a small sanity check for preventing destroying physics bodies during a tick.
#define LOG_FATAL(x)
Definition: Define.h:94
DLLEXPORT btTypedConstraint * GetConstraint()
std::vector< PhysicsConstraint::pointer > PhysicsConstraints
We need to keep constraints alive until they are destroyed.
DLLEXPORT void DetachResources()
This releases all resources held by this. This is called by the PhysicalWorld when this is destroyed ...
std::unique_ptr< btDiscreteDynamicsWorld > DynamicsWorld

◆ DestroyConstraintWrapper()

bool Leviathan::PhysicalWorld::DestroyConstraintWrapper ( PhysicsConstraint constraint)
inline

Definition at line 153 of file PhysicalWorld.h.

154  {
155  const auto result = DestroyConstraint(constraint);
156  if(constraint)
157  constraint->Release();
158  return result;
159  }
DLLEXPORT bool DestroyConstraint(PhysicsConstraint *constraint)
Destroys a physics constraint.

◆ GetGameWorld()

DLLEXPORT GameWorld* Leviathan::PhysicalWorld::GetGameWorld ( )
inline

Definition at line 121 of file PhysicalWorld.h.

122  {
123  return OwningWorld;
124  }

◆ GetMaterialPair()

const PhysMaterialDataPair * PhysicalWorld::GetMaterialPair ( int  id1,
int  id2 
) const

Finds the information for contact between objects with two materials.

Definition at line 236 of file PhysicalWorld.cpp.

237 {
238  const auto material1 = PhysicsMaterials->GetMaterial(id1);
239 
240  const PhysMaterialDataPair* pair = nullptr;
241 
242  // The logs in this method will absolutely trash performance if they get hit as there will
243  // be tons of calls with the same parameters
244 
245  if(material1) {
246  pair = material1->GetPairWith(id2);
247  } else {
248  LOG_ERROR("PhysicsBody has invalid material ID: " + std::to_string(id1));
249  }
250 
251  if(!pair) {
252 
253  const auto material2 = PhysicsMaterials->GetMaterial(id2);
254 
255  if(material2) {
256  pair = material2->GetPairWith(id1);
257  } else {
258  LOG_ERROR("PhysicsBody has invalid material ID: " + std::to_string(id2));
259  }
260  }
261 
262  return pair;
263 }
#define LOG_ERROR(x)
Definition: Define.h:92
Defines properties between two materials.
PhysicsMaterialManager * PhysicsMaterials
DLLEXPORT PhysicalMaterial * GetMaterial(const std::string &name)
Accesses material based on name.

◆ OnManifoldWithContact()

void PhysicalWorld::OnManifoldWithContact ( btPersistentManifold *  contactManifold,
const btManifoldPoint &  contactPoint,
const PhysMaterialDataPair pair,
PhysicsBody body1,
PhysicsBody body2 
)
protected

Calls appropriate material callbacks. This is called once per contact manifold that has penetrating points.

Definition at line 221 of file PhysicalWorld.cpp.

224 {
225  // Actual points touching
226  // const btVector3& contactPointA = contactPoint.getPositionWorldOnA();
227  // const btVector3& contactPointB = contactPoint.getPositionWorldOnB();
228  // const btVector3& normalOnB = contactPoint.m_normalWorldOnB;
229 
230  if(pair.ContactCallback) {
231 
232  pair.ContactCallback(*this, *body1, *body2);
233  }
234 }
PhysicsMaterialContactCallback ContactCallback

◆ OnPhysicsSubStep()

void PhysicalWorld::OnPhysicsSubStep ( btDynamicsWorld *  world,
btScalar  timeStep 
)
staticprotected

Definition at line 144 of file PhysicalWorld.cpp.

145 {
146  auto leviathanWorld = static_cast<PhysicalWorld*>(world->getWorldUserInfo());
147 
148  // Skip if no physics materials
149  if(!leviathanWorld->PhysicsMaterials)
150  return;
151 
152  btDispatcher* dispatcher = world->getDispatcher();
153 
154  // Check all active contacts as to whether something should be done
155  const int numManifolds = dispatcher->getNumManifolds();
156  for(int i = 0; i < numManifolds; i++) {
157 
158  btPersistentManifold* contactManifold = dispatcher->getManifoldByIndexInternal(i);
159 
160  const int numContacts = contactManifold->getNumContacts();
161 
162  if(numContacts < 1)
163  continue;
164 
165  const btCollisionObject* objA = contactManifold->getBody0();
166  const btCollisionObject* objB = contactManifold->getBody1();
167 
168  // TODO: remove this check once it is confirmed that both objects must always exist
169  if(objA && objB) {
170 
171  PhysicsBody* body1 = static_cast<PhysicsBody*>(objA->getUserPointer());
172  PhysicsBody* body2 = static_cast<PhysicsBody*>(objB->getUserPointer());
173 
174  // TODO: remove this check after confirming neither is ever null
175  if(body1 && body2) {
176 
177  // Find matching materials
178  const auto materialID1 = body1->GetPhysicalMaterialID();
179  const auto materialID2 = body2->GetPhysicalMaterialID();
180 
181  // Find contact callbacks
182  if(materialID1 >= 0 && materialID2 >= 0) {
183 
184  auto pair = leviathanWorld->GetMaterialPair(materialID1, materialID2);
185 
186  if(!pair)
187  continue;
188 
189  if(pair->ManifoldCallback) {
190 
191  pair->ManifoldCallback(
192  *leviathanWorld, *body1, *body2, *contactManifold);
193 
194  // Maybe release or clear here allows rechecking the AABB overlap
195  // dispatcher->releaseManifold()
196  }
197 
198  bool handled = false;
199 
200  for(int j = 0; j < numContacts; j++) {
201 
202  const btManifoldPoint& contactPoint =
203  contactManifold->getContactPoint(j);
204 
205  if(contactPoint.getDistance() < 0.f) {
206 
207  if(handled)
208  continue;
209 
210  handled = true;
211  leviathanWorld->OnManifoldWithContact(
212  contactManifold, contactPoint, *pair, body1, body2);
213  }
214  }
215  }
216  }
217  }
218  }
219 }
This is an instance of a collision body.
Definition: PhysicsBody.h:77
auto GetPhysicalMaterialID() const
Definition: PhysicsBody.h:177

◆ SetDebugDrawer()

DLLEXPORT void PhysicalWorld::SetDebugDrawer ( const std::shared_ptr< PhysicsDebugDrawer > &  drawer)

Sets or clears the debug drawer used by this world.

Definition at line 520 of file PhysicalWorld.cpp.

521 {
522  DebugDrawer = drawer;
523 
524  if(DebugDrawer) {
525  DynamicsWorld->setDebugDrawer(DebugDrawer.get());
526  } else {
527  DynamicsWorld->setDebugDrawer(nullptr);
528  }
529 }
std::shared_ptr< PhysicsDebugDrawer > DebugDrawer
std::unique_ptr< btDiscreteDynamicsWorld > DynamicsWorld

◆ SimulateWorld()

DLLEXPORT void PhysicalWorld::SimulateWorld ( float  secondspassed,
int  maxsubsteps = 8 
)

Advances the simulation the specified amount of time.

Todo:
Verify that this works correctly with the new variable rate ticks

Definition at line 130 of file PhysicalWorld.cpp.

131 {
133 
134  DynamicsWorld->stepSimulation(secondspassed, maxsubsteps);
135 
136  PhysicsUpdateInProgress = false;
137 
138  if(DebugDrawer) {
139  DebugDrawer->OnBeginDraw();
140  DynamicsWorld->debugDrawWorld();
141  }
142 }
bool PhysicsUpdateInProgress
This is a small sanity check for preventing destroying physics bodies during a tick.
std::shared_ptr< PhysicsDebugDrawer > DebugDrawer
std::unique_ptr< btDiscreteDynamicsWorld > DynamicsWorld

Member Data Documentation

◆ CollisionConfiguration

std::unique_ptr<btDefaultCollisionConfiguration> Leviathan::PhysicalWorld::CollisionConfiguration
protected

Definition at line 181 of file PhysicalWorld.h.

◆ DebugDrawer

std::shared_ptr<PhysicsDebugDrawer> Leviathan::PhysicalWorld::DebugDrawer
protected

Definition at line 199 of file PhysicalWorld.h.

◆ Dispatcher

std::unique_ptr<btCollisionDispatcher> Leviathan::PhysicalWorld::Dispatcher
protected

Definition at line 183 of file PhysicalWorld.h.

◆ DynamicsWorld

std::unique_ptr<btDiscreteDynamicsWorld> Leviathan::PhysicalWorld::DynamicsWorld
protected

Definition at line 189 of file PhysicalWorld.h.

◆ OverlapFilter

std::unique_ptr<LeviathanPhysicsOverlapFilter> Leviathan::PhysicalWorld::OverlapFilter
protected

Definition at line 191 of file PhysicalWorld.h.

◆ OverlappingPairCache

std::unique_ptr<btBroadphaseInterface> Leviathan::PhysicalWorld::OverlappingPairCache
protected

Definition at line 185 of file PhysicalWorld.h.

◆ OwningWorld

GameWorld* Leviathan::PhysicalWorld::OwningWorld
protected

Definition at line 174 of file PhysicalWorld.h.

◆ PassedTimeTotal

float Leviathan::PhysicalWorld::PassedTimeTotal = 0
protected

Total amount of seconds required to be simulated.

Definition at line 172 of file PhysicalWorld.h.

◆ PhysicsBodies

std::vector<PhysicsBody::pointer> Leviathan::PhysicalWorld::PhysicsBodies
protected

We need to keep the physic bodies alive (guaranteed) until they are destroyed.

Definition at line 194 of file PhysicalWorld.h.

◆ PhysicsConstraints

std::vector<PhysicsConstraint::pointer> Leviathan::PhysicalWorld::PhysicsConstraints
protected

We need to keep constraints alive until they are destroyed.

Definition at line 197 of file PhysicalWorld.h.

◆ PhysicsMaterials

PhysicsMaterialManager* Leviathan::PhysicalWorld::PhysicsMaterials
protected

Definition at line 175 of file PhysicalWorld.h.

◆ PhysicsUpdateInProgress

bool Leviathan::PhysicalWorld::PhysicsUpdateInProgress = false
protected

This is a small sanity check for preventing destroying physics bodies during a tick.

Definition at line 178 of file PhysicalWorld.h.

◆ Solver

std::unique_ptr<btSequentialImpulseConstraintSolver> Leviathan::PhysicalWorld::Solver
protected

Definition at line 187 of file PhysicalWorld.h.


The documentation for this class was generated from the following files: