3#pragma warning(disable: 4127)
4#pragma warning(disable: 5033)
6#include <BulletCollision/CollisionDispatch/btGhostObject.h>
11#include "PhysicsManager.h"
13#include "RigidBodySystem.h"
17#include "Services/Time.h"
18#include "ExtensionRegistry.h"
20#include "Components/Appearance/MaterialComponent.h"
22#include "GhostSystem.h"
25#include "Foundation/HashSequence.h"
26#include "Foundation/Collections/Pool.h"
27#include "Foundation/ComponentModel/Entity.h"
37Cogs::Core::PhysicsManager::PhysicsManager(Context * context) :
39 broadphase(
std::make_unique<btDbvtBroadphase>()),
40 collisionConfiguration(
std::make_unique<btDefaultCollisionConfiguration>()),
41 dispatcher(
std::make_unique<btCollisionDispatcher>(collisionConfiguration.get())),
42 solver(
std::make_unique<btSequentialImpulseConstraintSolver>()),
43 dynamicsWorld(
std::make_unique<btDiscreteDynamicsWorld>(dispatcher.get(), broadphase.get(), solver.get(), collisionConfiguration.get()))
45 dynamicsWorld->setGravity(btVector3(0, 0, -9.81f));
48Cogs::Core::PhysicsManager::~PhysicsManager() =
default;
50void Cogs::Core::PhysicsManager::addRigidBody(btRigidBody * rigidBody)
52 dynamicsWorld->addRigidBody(rigidBody);
55void Cogs::Core::PhysicsManager::removeRigidBody(btRigidBody * rigidBody)
57 dynamicsWorld->removeRigidBody(rigidBody);
60void Cogs::Core::PhysicsManager::addCollisionObject(btCollisionObject * btCollisionObject)
62 if (!ghostCallbackSet) {
63 dynamicsWorld->getPairCache()->setInternalGhostPairCallback(
new btGhostPairCallback());
64 ghostCallbackSet =
true;
67 dynamicsWorld->addCollisionObject(btCollisionObject, btBroadphaseProxy::CharacterFilter, btBroadphaseProxy::StaticFilter | btBroadphaseProxy::DefaultFilter);
70void Cogs::Core::PhysicsManager::removeCollisionObject(btCollisionObject * btCollisionObject)
72 dynamicsWorld->removeCollisionObject(btCollisionObject);
75void Cogs::Core::PhysicsManager::addConstraint(btTypedConstraint * constraint)
77 dynamicsWorld->addConstraint(constraint);
80void Cogs::Core::PhysicsManager::removeConstraint(btTypedConstraint * constraint)
82 dynamicsWorld->removeConstraint(constraint);
85void Cogs::Core::PhysicsManager::stepSimulation(
float deltaTime)
87 const float tick = 1.0f / 90.0f;
89 float scale = context->variables->get(timeScale, 1.0f);
90 dynamicsWorld->stepSimulation(deltaTime * scale, 10, tick);
93void Cogs::Core::CollisionDetail::registerType()
96 Field(
"idA", &CollisionDetail::idA),
97 Field(
"idB", &CollisionDetail::idB),
98 Field(
"positionA", &CollisionDetail::positionA),
99 Field(
"positionB", &CollisionDetail::positionB),
100 Field(
"impulse", &CollisionDetail::impulse),
103 TypeDatabase::createType<CollisionDetail>().setFields(fields);
107void Cogs::Core::PhysicsManager::preUpdate(Context* context)
109 if (task.isValid()) {
110 context->taskManager->wait(task);
115void Cogs::Core::PhysicsManager::postUpdate(Context* context)
118 auto elapsed = context->time->getAnimationTimeDelta();
121 CpuInstrumentationScope(SCOPE_PHYSICS,
"stepSimulation");
122 stepSimulation(
float(elapsed));
126void Cogs::Core::PhysicsManager::waitForASync(Context* context)
128 if (task.isValid()) {
129 context->taskManager->wait(task);
133void Cogs::Core::PhysicsManager::pullGhostState()
135 auto * ghostSystem = ExtensionRegistry::getExtensionSystem<GhostSystem>(context);
136 for (
auto & ghostComp : ghostSystem->pool) {
137 ghostComp.contacts.clear();
139 if (!ghostComp.isActive())
continue;
141 auto & ghostData = ghostSystem->getData(&ghostComp);
142 if(!ghostData.collisionObject)
continue;
144 auto & pairArray = ghostData.collisionObject->getOverlappingPairCache()->getOverlappingPairArray();
147 ghostComp.contacts.clear();
148 btManifoldArray manifoldArray;
149 for (
int i = 0; i < pairArray.size(); i++) {
150 manifoldArray.clear();
152 const auto & pair = pairArray[i];
153 auto * collisionPair = dynamicsWorld->getPairCache()->findPair(pair.m_pProxy0, pair.m_pProxy1);
154 if (!collisionPair || !collisionPair->m_algorithm)
continue;
156 collisionPair->m_algorithm->getAllContactManifolds(manifoldArray);
157 for (
int j = 0; j < manifoldArray.size(); j++) {
158 auto * manifold = manifoldArray[j];
160 bool noFlip = manifold->getBody0() == ghostData.collisionObject.get();
161 auto * objB = noFlip ? manifold->getBody1() : manifold->getBody0();
162 auto * dataB =
static_cast<SharedRigidBodyData *
>(objB->getUserPointer());
163 auto entityB = dataB->entity;
164 if(!entityB.lock())
continue;
166 for (
int k = 0; k < manifold->getNumContacts(); k++) {
167 const auto & pt = manifold->getContactPoint(k);
168 if (pt.getDistance() < 0.f && ghostComp.contacts.size() < 1024) {
170 ghostComp.contacts.push_back(GhostContact{
172 (noFlip ? -1.f : 1.f)*(*
reinterpret_cast<const glm::vec3 *
>(&pt.m_normalWorldOnB)),
173 *
reinterpret_cast<const glm::vec3 *
>(noFlip ? &pt.m_positionWorldOnA : &pt.m_positionWorldOnB),
185void Cogs::Core::PhysicsManager::pushGhostState()
187 auto * ghostSystem = ExtensionRegistry::getExtensionSystem<GhostSystem>(context);
188 auto * rigidBodySystem = ExtensionRegistry::getExtensionSystem<RigidBodySystem>(context);
190 for (
auto & ghostComp : ghostSystem->pool) {
192 for (
auto & action : ghostComp.actions) {
193 if (
auto e = action.target.lock(); e) {
194 if (
auto * c = e->getComponent<RigidBodyComponent>(); c) {
195 if (
auto & d = rigidBodySystem->getData(c); d.rigidBody) {
199 case GhostAction::ApplyImpulse:
200 d.rigidBody->applyImpulse(toBullet(action.value), toBullet(action.position));
201 d.rigidBody->activate();
212 ghostComp.actions.clear();
static constexpr TaskQueueId GlobalQueue
Global task queue.
Field definition describing a single data member of a data structure.
Provides a weakly referenced view over the contents of a string.
Contains reflection support.