From 4277332f7fdbe59c82a2bf44ea4046403e782556 Mon Sep 17 00:00:00 2001 From: turanszkij Date: Sun, 23 Sep 2018 19:40:14 +0100 Subject: [PATCH] physics rewrite --- Editor/ObjectWindow.cpp | 43 +- Editor/ObjectWindow.h | 1 + WickedEngine/MainComponent.cpp | 10 - WickedEngine/MainComponent.h | 3 - WickedEngine/WickedEngine.h | 3 +- WickedEngine/WickedEngine_SHARED.vcxitems | 5 +- .../WickedEngine_SHARED.vcxitems.filters | 15 +- WickedEngine/wiBULLET.cpp | 825 ------------------ WickedEngine/wiBULLET.h | 37 - WickedEngine/wiInitializer.cpp | 4 + WickedEngine/wiPHYSICS.h | 60 +- WickedEngine/wiPhysics_Bullet.cpp | 466 ++++++++++ WickedEngine/wiSceneSystem.cpp | 54 +- WickedEngine/wiSceneSystem.h | 19 +- WickedEngine/wiSceneSystem_Serializers.cpp | 2 - 15 files changed, 526 insertions(+), 1021 deletions(-) delete mode 100644 WickedEngine/wiBULLET.cpp delete mode 100644 WickedEngine/wiBULLET.h create mode 100644 WickedEngine/wiPhysics_Bullet.cpp diff --git a/Editor/ObjectWindow.cpp b/Editor/ObjectWindow.cpp index e076b96e7..428bbb349 100644 --- a/Editor/ObjectWindow.cpp +++ b/Editor/ObjectWindow.cpp @@ -94,33 +94,26 @@ ObjectWindow::ObjectWindow(wiGUI* gui) : GUI(gui) rigidBodyCheckBox->OnClick([&](wiEventArgs args) { Scene& scene = wiRenderer::GetScene(); + RigidBodyPhysicsComponent* physicscomponent = scene.rigidbodies.GetComponent(entity); + if (args.bValue) { - TransformComponent* transform = scene.transforms.GetComponent(entity); - ObjectComponent* object = scene.objects.GetComponent(entity); - if (transform != nullptr && object != nullptr) + if (physicscomponent == nullptr) { - MeshComponent* mesh = scene.meshes.GetComponent(object->meshID); - - RigidBodyPhysicsComponent* physicscomponent = scene.rigidbodies.GetComponent(entity); - if (physicscomponent == nullptr) - { - RigidBodyPhysicsComponent& rigidbody = scene.rigidbodies.Create(entity); - rigidbody.kinematic = kinematicCheckBox->GetCheck(); - rigidbody.shape = (RigidBodyPhysicsComponent::CollisionShape)collisionShapeComboBox->GetSelected(); - //wiRenderer::physicsEngine->addRigidBody(rigidbody, *mesh, *transform); - } + RigidBodyPhysicsComponent& rigidbody = scene.rigidbodies.Create(entity); + rigidbody.SetKinematic(kinematicCheckBox->GetCheck()); + rigidbody.SetDisableDeactivation(disabledeactivationCheckBox->GetCheck()); + rigidbody.shape = (RigidBodyPhysicsComponent::CollisionShape)collisionShapeComboBox->GetSelected(); } } else { - RigidBodyPhysicsComponent* physicscomponent = wiRenderer::GetScene().rigidbodies.GetComponent(entity); if (physicscomponent != nullptr) { - //wiRenderer::physicsEngine->removeRigidBody(*physicscomponent); - //scene.rigidbodies.Remove(entity); + scene.rigidbodies.Remove(entity); } } + }); objectWindow->AddWidget(rigidBodyCheckBox); @@ -132,11 +125,24 @@ ObjectWindow::ObjectWindow(wiGUI* gui) : GUI(gui) RigidBodyPhysicsComponent* physicscomponent = wiRenderer::GetScene().rigidbodies.GetComponent(entity); if (physicscomponent != nullptr) { - physicscomponent->kinematic = args.bValue; + physicscomponent->SetKinematic(args.bValue); } }); objectWindow->AddWidget(kinematicCheckBox); + disabledeactivationCheckBox = new wiCheckBox("Disable Deactivation: "); + disabledeactivationCheckBox->SetTooltip("Toggle kinematic behaviour."); + disabledeactivationCheckBox->SetPos(XMFLOAT2(x, y += 30)); + disabledeactivationCheckBox->SetCheck(false); + disabledeactivationCheckBox->OnClick([&](wiEventArgs args) { + RigidBodyPhysicsComponent* physicscomponent = wiRenderer::GetScene().rigidbodies.GetComponent(entity); + if (physicscomponent != nullptr) + { + physicscomponent->SetDisableDeactivation(args.bValue); + } + }); + objectWindow->AddWidget(disabledeactivationCheckBox); + collisionShapeComboBox = new wiComboBox("Collision Shape:"); collisionShapeComboBox->SetSize(XMFLOAT2(100, 20)); collisionShapeComboBox->SetPos(XMFLOAT2(x, y += 30)); @@ -218,7 +224,8 @@ void ObjectWindow::SetEntity(Entity entity) if (physicsComponent != nullptr) { - kinematicCheckBox->SetCheck(physicsComponent->kinematic); + kinematicCheckBox->SetCheck(physicsComponent->IsKinematic()); + disabledeactivationCheckBox->SetCheck(physicsComponent->IsDisableDeactivation()); if (physicsComponent->shape == RigidBodyPhysicsComponent::CollisionShape::BOX) { diff --git a/Editor/ObjectWindow.h b/Editor/ObjectWindow.h index 8c734d699..678b8309d 100644 --- a/Editor/ObjectWindow.h +++ b/Editor/ObjectWindow.h @@ -28,6 +28,7 @@ public: wiLabel* physicsLabel; wiCheckBox* rigidBodyCheckBox; + wiCheckBox* disabledeactivationCheckBox; wiCheckBox* kinematicCheckBox; wiComboBox* collisionShapeComboBox; }; diff --git a/WickedEngine/MainComponent.cpp b/WickedEngine/MainComponent.cpp index f84878f56..c4b5184a8 100644 --- a/WickedEngine/MainComponent.cpp +++ b/WickedEngine/MainComponent.cpp @@ -14,8 +14,6 @@ #include "wiProfiler.h" #include "wiInitializer.h" #include "wiStartupArguments.h" -#include "wiPHYSICS.h" -#include "wiBULLET.h" #include "wiGraphicsDevice_DX11.h" #include "wiGraphicsDevice_DX12.h" @@ -43,16 +41,12 @@ MainComponent::MainComponent() infoDisplay = InfoDisplayer(); fadeManager.Clear(); - - physicsEngine = new wiBULLET; } MainComponent::~MainComponent() { wiRenderer::GetDevice()->WaitForGPU(); - - SAFE_DELETE(physicsEngine); } void MainComponent::Initialize() @@ -154,10 +148,6 @@ void MainComponent::Run() } wiProfiler::GetInstance().EndRange(); // Fixed Update - wiProfiler::GetInstance().BeginRange("Physics", wiProfiler::DOMAIN_CPU); - physicsEngine->Update((float)elapsedTime); - wiProfiler::GetInstance().EndRange(); // Physics - wiLua::GetGlobal()->SetDeltaTime(elapsedTime); // Variable-timed update: diff --git a/WickedEngine/MainComponent.h b/WickedEngine/MainComponent.h index 9c05e6b75..49556ad05 100644 --- a/WickedEngine/MainComponent.h +++ b/WickedEngine/MainComponent.h @@ -6,7 +6,6 @@ #include "wiWindowRegistration.h" class RenderableComponent; -class PHYSICS; class MainComponent { @@ -25,8 +24,6 @@ public: int screenW, screenH; bool fullscreen; - PHYSICS* physicsEngine = nullptr; - // Runs the main engine loop void Run(); diff --git a/WickedEngine/WickedEngine.h b/WickedEngine/WickedEngine.h index 27d9c1441..b0b13a4b0 100644 --- a/WickedEngine/WickedEngine.h +++ b/WickedEngine/WickedEngine.h @@ -37,8 +37,7 @@ #include "wiTextureHelper.h" #include "wiRandom.h" #include "wiColor.h" -#include "wiPHYSICS.h" -#include "wiBULLET.h" +#include "wiPhysics.h" #include "wiEnums.h" #include "wiInitializer.h" #include "wiLua.h" diff --git a/WickedEngine/WickedEngine_SHARED.vcxitems b/WickedEngine/WickedEngine_SHARED.vcxitems index 80c728c8d..a1a49b46d 100644 --- a/WickedEngine/WickedEngine_SHARED.vcxitems +++ b/WickedEngine/WickedEngine_SHARED.vcxitems @@ -309,7 +309,6 @@ - @@ -339,6 +338,7 @@ + @@ -347,7 +347,6 @@ - @@ -654,7 +653,6 @@ - @@ -679,6 +677,7 @@ + diff --git a/WickedEngine/WickedEngine_SHARED.vcxitems.filters b/WickedEngine/WickedEngine_SHARED.vcxitems.filters index cb15240d0..0b1d574e8 100644 --- a/WickedEngine/WickedEngine_SHARED.vcxitems.filters +++ b/WickedEngine/WickedEngine_SHARED.vcxitems.filters @@ -951,9 +951,6 @@ ENGINE\Audio - - ENGINE\Physics - ENGINE\Graphics @@ -1002,9 +999,6 @@ ENGINE\Input - - ENGINE\Physics - ENGINE\Tools @@ -1143,6 +1137,9 @@ ENGINE\Helpers + + ENGINE\Physics + @@ -1814,9 +1811,6 @@ ENGINE\Audio - - ENGINE\Physics - ENGINE\Graphics @@ -1934,6 +1928,9 @@ ENGINE\Scripting\LuaBindings + + ENGINE\Physics + diff --git a/WickedEngine/wiBULLET.cpp b/WickedEngine/wiBULLET.cpp deleted file mode 100644 index 541ec1a28..000000000 --- a/WickedEngine/wiBULLET.cpp +++ /dev/null @@ -1,825 +0,0 @@ -#include "wiBULLET.h" -#include "wiSceneSystem.h" -#include "wiRenderer.h" - -#include "btBulletDynamicsCommon.h" - -#include "LinearMath/btHashMap.h" -#include "BulletSoftBody/btSoftRigidDynamicsWorld.h" -#include "BulletSoftBody/btSoftBodyHelpers.h" - -#include "BulletSoftBody/btSoftBodySolvers.h" -#include "BulletSoftBody/btDefaultSoftBodySolver.h" -#include "BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h" - -using namespace std; -using namespace wiSceneSystem; -using namespace wiECS; - -int PHYSICS::softBodyIterationCount=5; -bool PHYSICS::rigidBodyPhysicsEnabled = true, PHYSICS::softBodyPhysicsEnabled = true; - -struct BulletPhysicsWorld -{ - btCollisionConfiguration* collisionConfiguration; - btCollisionDispatcher* dispatcher; - btBroadphaseInterface* overlappingPairCache; - btSequentialImpulseConstraintSolver* solver; - btDynamicsWorld* dynamicsWorld; - btAlignedObjectArray collisionShapes; - - btSoftBodySolver* softBodySolver; - btSoftBodySolverOutput* softBodySolverOutput; - - btVector3 wind; -}; - -wiBULLET::wiBULLET() -{ - bulletPhysics = new BulletPhysicsWorld; - - registeredObjects=-1; - - ///-----initialization_start----- - //softBodySolver = new btDefaultSoftBodySolver(); - bulletPhysics->softBodySolver = nullptr; - - ///collision configuration contains default setup for memory, collision setup. Advanced users can create their own configuration. - //collisionConfiguration = new btDefaultCollisionConfiguration(); - bulletPhysics->collisionConfiguration = new btSoftBodyRigidBodyCollisionConfiguration(); - - ///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded) - bulletPhysics->dispatcher = new btCollisionDispatcher(bulletPhysics->collisionConfiguration); - - ///btDbvtBroadphase is a good general purpose broadphase. You can also try out btAxis3Sweep. - bulletPhysics->overlappingPairCache = new btDbvtBroadphase(); - - ///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded) - bulletPhysics->solver = new btSequentialImpulseConstraintSolver; - - //dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,overlappingPairCache,solver,collisionConfiguration); - bulletPhysics->dynamicsWorld = new btSoftRigidDynamicsWorld(bulletPhysics->dispatcher, bulletPhysics->overlappingPairCache, bulletPhysics->solver, bulletPhysics->collisionConfiguration, bulletPhysics->softBodySolver); - - - bulletPhysics->dynamicsWorld->getSolverInfo().m_solverMode|=SOLVER_RANDMIZE_ORDER; - bulletPhysics->dynamicsWorld->getDispatchInfo().m_enableSatConvex = true; - bulletPhysics->dynamicsWorld->getSolverInfo().m_splitImpulse=true; - - bulletPhysics->dynamicsWorld->setGravity(btVector3(0,-11,0)); - ((btSoftRigidDynamicsWorld*)bulletPhysics->dynamicsWorld)->getWorldInfo().air_density = (btScalar)0.0; - ((btSoftRigidDynamicsWorld*)bulletPhysics->dynamicsWorld)->getWorldInfo().water_density = 0; - ((btSoftRigidDynamicsWorld*)bulletPhysics->dynamicsWorld)->getWorldInfo().water_offset = 0; - ((btSoftRigidDynamicsWorld*)bulletPhysics->dynamicsWorld)->getWorldInfo().water_normal = btVector3(0,0,0); - ((btSoftRigidDynamicsWorld*)bulletPhysics->dynamicsWorld)->getWorldInfo().m_gravity.setValue(0,-11,0); - ((btSoftRigidDynamicsWorld*)bulletPhysics->dynamicsWorld)->getWorldInfo().m_sparsesdf.Initialize(); //??? - - //dynamicsWorld->setInternalTickCallback(soundTickCallback,this,true); - //dynamicsWorld->setInternalTickCallback(pickingPreTickCallback,this,true); - - -#ifdef BACKLOG - wiBackLog::post("wiBULLET physics Initialized"); -#endif - - ///-----initialization_end----- -} - -wiBULLET::~wiBULLET() -{ - //cleanup in the reverse order of creation/initialization - - ///-----cleanup_start----- - - ClearWorld(); - - //delete dynamics world - delete bulletPhysics->dynamicsWorld; - - //delete solver - delete bulletPhysics->solver; - - //delete broadphase - delete bulletPhysics->overlappingPairCache; - - //delete dispatcher - delete bulletPhysics->dispatcher; - - delete bulletPhysics->collisionConfiguration; - - //next line is optional: it will be cleared by the destructor when the array goes out of scope - bulletPhysics->collisionShapes.clear(); - - ///-----cleanup_end----- - CleanUp(); - - delete bulletPhysics; -} - - -void wiBULLET::setWind(const XMFLOAT3& wind){ - this->bulletPhysics->wind = btVector3(btScalar(wind.x),btScalar(wind.y),btScalar(wind.z)); -} - - -void wiBULLET::connectVerticesToSoftBody(wiSceneSystem::SoftBodyPhysicsComponent& physicscomponent, wiSceneSystem::MeshComponent& mesh) -{ - //if (!softBodyPhysicsEnabled) - // return; - - //btCollisionObject* obj = bulletPhysics->dynamicsWorld->getCollisionObjectArray()[physicscomponent.physicsObjectID]; - //btSoftBody* softBody = btSoftBody::upcast(obj); - - //if (softBody) - //{ - // btVector3 min, max; - // softBody->getAabb(min, max); - // mesh.aabb.create(XMFLOAT3(min.x(), min.y(), min.z()), XMFLOAT3(max.x(), max.y(), max.z())); - - // softBody->setWindVelocity(bulletPhysics->wind); - - // btSoftBody::tNodeArray& nodes(softBody->m_nodes); - - // int gvg = physicscomponent.goalVG; - // for (size_t i = 0; i < mesh.vertex_positions.size(); ++i) - // { - // int indexP = physicscomponent.physicalmapGP[i]; - // float weight = mesh.vertexGroups[gvg].vertex_weights[indexP]; - - // MeshComponent::Vertex_POS& vert = mesh.vertices_Transformed_POS[i]; - - // mesh.vertices_Transformed_PRE[i] = vert; - // vert.pos.x = nodes[indexP].m_x.getX(); - // vert.pos.y = nodes[indexP].m_x.getY(); - // vert.pos.z = nodes[indexP].m_x.getZ(); - // mesh.vertices_Transformed_POS[i].MakeFromParams(XMFLOAT3(-nodes[indexP].m_n.getX(), -nodes[indexP].m_n.getY(), -nodes[indexP].m_n.getZ())/*, vert.GetWind(), vert.GetMaterialIndex()*/); - // } - //} -} -void wiBULLET::connectSoftBodyToVertices(wiSceneSystem::SoftBodyPhysicsComponent& physicscomponent, wiSceneSystem::MeshComponent& mesh) -{ - //if (!softBodyPhysicsEnabled) - // return; - - //if (!firstRunWorld) - //{ - // btCollisionObject* obj = bulletPhysics->dynamicsWorld->getCollisionObjectArray()[physicscomponent.physicsObjectID]; - // btSoftBody* softBody = btSoftBody::upcast(obj); - - // if (softBody) { - // btSoftBody::tNodeArray& nodes(softBody->m_nodes); - - // int gvg = physicscomponent.goalVG; - // if (gvg >= 0) - // { - // int j = 0; - // for (auto it = mesh.vertexGroups[gvg].vertex_weights.begin(); it != mesh.vertexGroups[gvg].vertex_weights.end(); ++it) - // { - // int vi = (*it).first; - // int index = physicscomponent.physicalmapGP[vi]; - // float weight = (*it).second; - // nodes[index].m_x = nodes[index].m_x.lerp(btVector3(physicscomponent.goalPositions[j].x, physicscomponent.goalPositions[j].y, physicscomponent.goalPositions[j].z), weight); - // ++j; - // } - // } - // } - //} -} -void wiBULLET::transformBody(const XMFLOAT4& rot, const XMFLOAT3& pos, int objectI) -{ - if (objectI < 0) - { - return; - } - - btCollisionObject* obj = bulletPhysics->dynamicsWorld->getCollisionObjectArray()[objectI]; - btRigidBody* rigidBody = btRigidBody::upcast(obj); - if (rigidBody) - { - btTransform transform; - transform.setIdentity(); - transform.setRotation(btQuaternion(rot.x, rot.y, rot.z, rot.w)); - transform.setOrigin(btVector3(pos.x, pos.y, pos.z)); - rigidBody->getMotionState()->setWorldTransform(transform); - } -} - -PHYSICS::PhysicsTransform* wiBULLET::getObject(int index) -{ - - btCollisionObject* obj = bulletPhysics->dynamicsWorld->getCollisionObjectArray()[index]; - btTransform trans; - - btRigidBody* body = btRigidBody::upcast(obj); - if (body && body->getMotionState()) - { - body->getMotionState()->getWorldTransform(trans); - } - - btSoftBody* softBody = btSoftBody::upcast(obj); - if(softBody) - { - trans = softBody->getWorldTransform(); - } - - btQuaternion rot = trans.getRotation(); - btVector3 pos = trans.getOrigin(); - transforms[index]->rotation=XMFLOAT4(rot.getX(),rot.getY(),rot.getZ(),rot.getW()); - transforms[index]->position=XMFLOAT3(pos.getX(),pos.getY(),pos.getZ()); - return transforms[index]; -} - -void wiBULLET::addRigidBody(wiSceneSystem::RigidBodyPhysicsComponent& physicscomponent, wiSceneSystem::MeshComponent& mesh, wiSceneSystem::TransformComponent& transform) -{ - if (!rigidBodyPhysicsEnabled) - { - return; - } - - btVector3 S = btVector3(transform.scale_local.x, transform.scale_local.y, transform.scale_local.z); - btQuaternion R = btQuaternion(transform.rotation_local.x, transform.rotation_local.y, transform.rotation_local.z, transform.rotation_local.z); - btVector3 T = btVector3(transform.translation_local.x, transform.translation_local.y, transform.translation_local.z); - - switch(physicscomponent.shape) - { - case RigidBodyPhysicsComponent::CollisionShape::BOX: - { - btCollisionShape* shape = new btBoxShape(S); - shape->setMargin(btScalar(0.05)); - bulletPhysics->collisionShapes.push_back(shape); - - btTransform shapeTransform; - shapeTransform.setIdentity(); - shapeTransform.setOrigin(T); - shapeTransform.setRotation(R); - { - btScalar mass(physicscomponent.mass); - - //rigidbody is dynamic if and only if mass is non zero, otherwise static - bool isDynamic = (mass != 0.f && !physicscomponent.kinematic); - - btVector3 localInertia(0, 0, 0); - if (isDynamic) - shape->calculateLocalInertia(mass, localInertia); - else - mass = 0; - - //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects - btDefaultMotionState* myMotionState = new btDefaultMotionState(shapeTransform); - btRigidBody::btRigidBodyConstructionInfo rbInfo(mass, myMotionState, shape, localInertia); - rbInfo.m_friction = physicscomponent.friction; - rbInfo.m_restitution = physicscomponent.restitution; - rbInfo.m_linearDamping = physicscomponent.damping; - rbInfo.m_angularDamping = physicscomponent.damping; - btRigidBody* body = new btRigidBody(rbInfo); - if (physicscomponent.kinematic) - body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); - body->setActivationState(DISABLE_DEACTIVATION); - - //add the body to the dynamics world - bulletPhysics->dynamicsWorld->addRigidBody(body); - - - if (body->getMotionState()) - { - btTransform trans; - body->getMotionState()->getWorldTransform(trans); - btQuaternion nRot = trans.getRotation(); - btVector3 nPos = trans.getOrigin(); - transforms.push_back(new PhysicsTransform( - XMFLOAT4(nRot.getX(), nRot.getY(), nRot.getZ(), nRot.getW()), XMFLOAT3(nPos.getX(), nPos.getY(), nPos.getZ())) - ); - } - } - } - break; - - case RigidBodyPhysicsComponent::CollisionShape::SPHERE: - { - btCollisionShape* shape = new btSphereShape(btScalar(S.x())); - shape->setMargin(btScalar(0.05)); - bulletPhysics->collisionShapes.push_back(shape); - - btTransform shapeTransform; - shapeTransform.setIdentity(); - shapeTransform.setOrigin(T); - { - btScalar mass(physicscomponent.mass); - - //rigidbody is dynamic if and only if mass is non zero, otherwise static - bool isDynamic = (mass != 0.f && !physicscomponent.kinematic); - - btVector3 localInertia(0, 0, 0); - if (isDynamic) - shape->calculateLocalInertia(mass, localInertia); - else - mass = 0; - - //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects - btDefaultMotionState* myMotionState = new btDefaultMotionState(shapeTransform); - btRigidBody::btRigidBodyConstructionInfo rbInfo(mass, myMotionState, shape, localInertia); - rbInfo.m_friction = physicscomponent.friction; - rbInfo.m_restitution = physicscomponent.restitution; - rbInfo.m_linearDamping = physicscomponent.damping; - rbInfo.m_angularDamping = physicscomponent.damping; - btRigidBody* body = new btRigidBody(rbInfo); - if (physicscomponent.kinematic) - body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); - body->setActivationState(DISABLE_DEACTIVATION); - - //add the body to the dynamics world - bulletPhysics->dynamicsWorld->addRigidBody(body); - - - if (body->getMotionState()) - { - btTransform trans; - body->getMotionState()->getWorldTransform(trans); - btQuaternion nRot = trans.getRotation(); - btVector3 nPos = trans.getOrigin(); - transforms.push_back(new PhysicsTransform( - XMFLOAT4(nRot.getX(), nRot.getY(), nRot.getZ(), nRot.getW()), XMFLOAT3(nPos.getX(), nPos.getY(), nPos.getZ())) - ); - } - } - - } - break; - - case RigidBodyPhysicsComponent::CollisionShape::CAPSULE: - { - btCollisionShape* shape = new btCapsuleShape(btScalar(S.x()), btScalar(S.y())); - shape->setMargin(btScalar(0.05)); - bulletPhysics->collisionShapes.push_back(shape); - - btTransform shapeTransform; - shapeTransform.setIdentity(); - shapeTransform.setOrigin(T); - shapeTransform.setRotation(R); - { - btScalar mass(physicscomponent.mass); - - //rigidbody is dynamic if and only if mass is non zero, otherwise static - bool isDynamic = (mass != 0.f && !physicscomponent.kinematic); - - btVector3 localInertia(0, 0, 0); - if (isDynamic) - shape->calculateLocalInertia(mass, localInertia); - else - mass = 0; - - //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects - btDefaultMotionState* myMotionState = new btDefaultMotionState(shapeTransform); - btRigidBody::btRigidBodyConstructionInfo rbInfo(mass, myMotionState, shape, localInertia); - rbInfo.m_friction = physicscomponent.friction; - rbInfo.m_restitution = physicscomponent.restitution; - rbInfo.m_linearDamping = physicscomponent.damping; - rbInfo.m_angularDamping = physicscomponent.damping; - btRigidBody* body = new btRigidBody(rbInfo); - if (physicscomponent.kinematic) - body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); - body->setActivationState(DISABLE_DEACTIVATION); - - //add the body to the dynamics world - bulletPhysics->dynamicsWorld->addRigidBody(body); - - - if (body->getMotionState()) - { - btTransform trans; - body->getMotionState()->getWorldTransform(trans); - btQuaternion nRot = trans.getRotation(); - btVector3 nPos = trans.getOrigin(); - transforms.push_back(new PhysicsTransform( - XMFLOAT4(nRot.getX(), nRot.getY(), nRot.getZ(), nRot.getW()), XMFLOAT3(nPos.getX(), nPos.getY(), nPos.getZ())) - ); - } - } - } - break; - - case RigidBodyPhysicsComponent::CollisionShape::CONVEX_HULL: - { - btCollisionShape* shape = new btConvexHullShape(); - for (auto& pos : mesh.vertex_positions) - { - ((btConvexHullShape*)shape)->addPoint(btVector3(pos.x, pos.y, pos.z)); - } - shape->setLocalScaling(S); - shape->setMargin(btScalar(0.05)); - - bulletPhysics->collisionShapes.push_back(shape); - - btTransform shapeTransform; - shapeTransform.setIdentity(); - shapeTransform.setOrigin(T); - shapeTransform.setRotation(R); - { - btScalar mass(physicscomponent.mass); - - //rigidbody is dynamic if and only if mass is non zero, otherwise static - bool isDynamic = (mass != 0.f && !physicscomponent.kinematic); - - btVector3 localInertia(0, 0, 0); - if (isDynamic) - shape->calculateLocalInertia(mass, localInertia); - else - mass = 0; - - //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects - btDefaultMotionState* myMotionState = new btDefaultMotionState(shapeTransform); - btRigidBody::btRigidBodyConstructionInfo rbInfo(mass, myMotionState, shape, localInertia); - rbInfo.m_friction = physicscomponent.friction; - rbInfo.m_restitution = physicscomponent.restitution; - rbInfo.m_linearDamping = physicscomponent.damping; - rbInfo.m_angularDamping = physicscomponent.damping; - btRigidBody* body = new btRigidBody(rbInfo); - if (physicscomponent.kinematic) - body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); - body->setActivationState(DISABLE_DEACTIVATION); - - //add the body to the dynamics world - bulletPhysics->dynamicsWorld->addRigidBody(body); - - - if (body->getMotionState()) - { - btTransform trans; - body->getMotionState()->getWorldTransform(trans); - btQuaternion nRot = trans.getRotation(); - btVector3 nPos = trans.getOrigin(); - transforms.push_back(new PhysicsTransform( - XMFLOAT4(nRot.getX(), nRot.getY(), nRot.getZ(), nRot.getW()), XMFLOAT3(nPos.getX(), nPos.getY(), nPos.getZ())) - ); - } - } - } - break; - - case RigidBodyPhysicsComponent::CollisionShape::TRIANGLE_MESH: - { - int totalVerts = (int)mesh.vertex_positions.size(); - int totalTriangles = (int)mesh.indices.size() / 3; - - btVector3* btVerts = new btVector3[totalVerts]; - size_t i = 0; - for (auto& pos : mesh.vertex_positions) - { - btVerts[i++] = btVector3(pos.x, pos.y, pos.z); - } - - int* btInd = new int[mesh.indices.size()]; - i = 0; - for (auto& ind : mesh.indices) - { - btInd[i++] = ind; - } - - int vertStride = sizeof(btVector3); - int indexStride = 3 * sizeof(int); - - btTriangleIndexVertexArray* indexVertexArrays = new btTriangleIndexVertexArray( - totalTriangles, - btInd, - indexStride, - totalVerts, - (btScalar*)&btVerts[0].x(), - vertStride - ); - - bool useQuantizedAabbCompression = true; - - btCollisionShape* shape = new btBvhTriangleMeshShape(indexVertexArrays, useQuantizedAabbCompression); - shape->setMargin(btScalar(0.05)); - shape->setLocalScaling(S); - - bulletPhysics->collisionShapes.push_back(shape); - - btTransform shapeTransform; - shapeTransform.setIdentity(); - shapeTransform.setOrigin(T); - shapeTransform.setRotation(R); - { - btScalar mass(physicscomponent.mass); - - //rigidbody is dynamic if and only if mass is non zero, otherwise static - bool isDynamic = (mass != 0.f && !physicscomponent.kinematic); - - btVector3 localInertia(0, 0, 0); - if (isDynamic) - shape->calculateLocalInertia(mass, localInertia); - else - mass = 0; - - //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects - btDefaultMotionState* myMotionState = new btDefaultMotionState(shapeTransform); - btRigidBody::btRigidBodyConstructionInfo rbInfo(mass, myMotionState, shape, localInertia); - rbInfo.m_friction = physicscomponent.friction; - rbInfo.m_restitution = physicscomponent.restitution; - rbInfo.m_linearDamping = physicscomponent.damping; - rbInfo.m_angularDamping = physicscomponent.damping; - btRigidBody* body = new btRigidBody(rbInfo); - if (physicscomponent.kinematic) - body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); - body->setActivationState(DISABLE_DEACTIVATION); - - //add the body to the dynamics world - bulletPhysics->dynamicsWorld->addRigidBody(body); - - - if (body->getMotionState()) - { - btTransform trans; - body->getMotionState()->getWorldTransform(trans); - btQuaternion nRot = trans.getRotation(); - btVector3 nPos = trans.getOrigin(); - transforms.push_back(new PhysicsTransform( - XMFLOAT4(nRot.getX(), nRot.getY(), nRot.getZ(), nRot.getW()), XMFLOAT3(nPos.getX(), nPos.getY(), nPos.getZ())) - ); - } - } - } - } - - - - physicscomponent.physicsObjectID = ++registeredObjects; -} -void wiBULLET::addSoftBody(wiSceneSystem::SoftBodyPhysicsComponent& physicscomponent, wiSceneSystem::MeshComponent& mesh, wiSceneSystem::TransformComponent& transform) -{ - if (!softBodyPhysicsEnabled) - { - return; - } - - btVector3 S = btVector3(transform.scale_local.x, transform.scale_local.y, transform.scale_local.z); - btQuaternion R = btQuaternion(transform.rotation_local.x, transform.rotation_local.y, transform.rotation_local.z, transform.rotation_local.z); - btVector3 T = btVector3(transform.translation_local.x, transform.translation_local.y, transform.translation_local.z); - - { - const int vCount = (int)physicscomponent.physicsvertices.size(); - btScalar* btVerts = new btScalar[vCount * 3]; - for (int i = 0; idynamicsWorld)->getWorldInfo() - , &btVerts[0] - , &btInd[0] - , tCount - , false - ); - - - delete[] btVerts; - delete[] btInd; - - if (softBody) - { - btSoftBody::Material* pm = softBody->appendMaterial(); - pm->m_kLST = 0.5; - pm->m_kVST = 0.5; - pm->m_kAST = 0.5; - pm->m_flags = 0; - softBody->generateBendingConstraints(2, pm); - softBody->randomizeConstraints(); - - btTransform shapeTransform; - shapeTransform.setIdentity(); - shapeTransform.setOrigin(T); - shapeTransform.setRotation(R); - softBody->scale(S); - softBody->transform(shapeTransform); - - - softBody->m_cfg.piterations = softBodyIterationCount; - softBody->m_cfg.aeromodel = btSoftBody::eAeroModel::F_TwoSidedLiftDrag; - - softBody->m_cfg.kAHR = btScalar(.69); //0.69 Anchor hardness [0,1] - softBody->m_cfg.kCHR = btScalar(1.0); //1 Rigid contact hardness [0,1] - softBody->m_cfg.kDF = btScalar(physicscomponent.friction); //0.2 Dynamic friction coefficient [0,1] - softBody->m_cfg.kDG = btScalar(0.01); //0 Drag coefficient [0,+inf] - softBody->m_cfg.kDP = btScalar(0.0); //0 Damping coefficient [0,1] - softBody->m_cfg.kKHR = btScalar(0.1); //0.1 Kinetic contact hardness [0,1] - softBody->m_cfg.kLF = btScalar(0.1); //0 Lift coefficient [0,+inf] - softBody->m_cfg.kMT = btScalar(0.0); //0 Pose matching coefficient [0,1] - softBody->m_cfg.kPR = btScalar(0.0); //0 Pressure coefficient [-1,1] - softBody->m_cfg.kSHR = btScalar(1.0); //1 Soft contacts hardness [0,1] - softBody->m_cfg.kVC = btScalar(0.0); //0 Volume conseration coefficient [0,+inf] - softBody->m_cfg.kVCF = btScalar(1.0); //1 Velocities correction factor (Baumgarte) - - softBody->m_cfg.kSKHR_CL = btScalar(1.0); //1 Soft vs. kinetic hardness [0,1] - softBody->m_cfg.kSK_SPLT_CL = btScalar(0.5); //0.5 Soft vs. rigid impulse split [0,1] - softBody->m_cfg.kSRHR_CL = btScalar(0.1); //0.1 Soft vs. rigid hardness [0,1] - softBody->m_cfg.kSR_SPLT_CL = btScalar(0.5); //0.5 Soft vs. rigid impulse split [0,1] - softBody->m_cfg.kSSHR_CL = btScalar(0.5); //0.5 Soft vs. soft hardness [0,1] - softBody->m_cfg.kSS_SPLT_CL = btScalar(0.5); //0.5 Soft vs. rigid impulse split [0,1] - - - btScalar mass = btScalar(physicscomponent.mass); - softBody->setTotalMass(mass); - - //int mvg = physicscomponent.massVG; - //if (mvg >= 0) { - // for (auto it = mesh.vertexGroups[mvg].vertex_weights.begin(); it != mesh.vertexGroups[mvg].vertex_weights.end(); ++it) { - // int vi = (*it).first; - // float wei = (*it).second; - // int index = physicscomponent.physicalmapGP[vi]; - // softBody->setMass(index, softBody->getMass(index)*btScalar(wei)); - // } - //} - - - //int gvg = physicscomponent.goalVG; - //if (gvg >= 0) { - // for (auto it = mesh.vertexGroups[gvg].vertex_weights.begin(); it != mesh.vertexGroups[gvg].vertex_weights.end(); ++it) { - // int vi = (*it).first; - // int index = physicscomponent.physicalmapGP[vi]; - // float weight = (*it).second; - // if (weight == 1) - // softBody->setMass(index, 0); - // } - //} - - softBody->getCollisionShape()->setMargin(btScalar(0.2)); - - softBody->setWindVelocity(bulletPhysics->wind); - - softBody->setPose(true, true); - - softBody->setActivationState(DISABLE_DEACTIVATION); - - ((btSoftRigidDynamicsWorld*)bulletPhysics->dynamicsWorld)->addSoftBody(softBody); - - transforms.push_back(new PhysicsTransform); - } - } - - physicscomponent.physicsObjectID = ++registeredObjects; -} -void wiBULLET::removeRigidBody(wiSceneSystem::RigidBodyPhysicsComponent& physicscomponent) -{ - if (physicscomponent.physicsObjectID < 0) - { - return; - } - - deleteObject(physicscomponent.physicsObjectID); - - physicscomponent.physicsObjectID = -1; -} -void wiBULLET::removeSoftBody(wiSceneSystem::SoftBodyPhysicsComponent& physicscomponent) -{ - if (physicscomponent.physicsObjectID < 0) - { - return; - } - - deleteObject(physicscomponent.physicsObjectID); - - physicscomponent.physicsObjectID = -1; -} - -void wiBULLET::Update(float dt) -{ - if (rigidBodyPhysicsEnabled || softBodyPhysicsEnabled) - bulletPhysics->dynamicsWorld->stepSimulation(dt, 6); -} -void wiBULLET::ClearWorld() -{ - for (int i = bulletPhysics->dynamicsWorld->getNumCollisionObjects() - 1; i >= 0; i--) - { - deleteObject(i); - } - - //delete collision shapes - for (int j = 0; j < bulletPhysics->collisionShapes.size(); j++) - { - btCollisionShape* shape = bulletPhysics->collisionShapes[j]; - bulletPhysics->collisionShapes[j] = 0; - delete shape; - } - - //delete transfom interface - for (unsigned int i = 0; i < transforms.size(); ++i) - delete transforms[i]; - transforms.clear(); - registeredObjects = -1; -} -void wiBULLET::CleanUp() -{ - for (unsigned int i = 0; i < transforms.size(); ++i) - delete transforms[i]; - transforms.clear(); -} - -void wiBULLET::deleteObject(int id) -{ - btCollisionObject* obj = bulletPhysics->dynamicsWorld->getCollisionObjectArray()[id]; - btRigidBody* body = btRigidBody::upcast(obj); - - if (body && body->getMotionState()) - { - delete body->getMotionState(); - } - while (bulletPhysics->dynamicsWorld->getNumConstraints()) - { - btTypedConstraint* pc = bulletPhysics->dynamicsWorld->getConstraint(0); - bulletPhysics->dynamicsWorld->removeConstraint(pc); - delete pc; - } - - btSoftBody* softBody = btSoftBody::upcast(obj); - if (softBody) - { - ((btSoftRigidDynamicsWorld*)bulletPhysics->dynamicsWorld)->removeSoftBody(softBody); - } - else - { - btRigidBody* body = btRigidBody::upcast(obj); - if (body) - bulletPhysics->dynamicsWorld->removeRigidBody(body); - else - bulletPhysics->dynamicsWorld->removeCollisionObject(obj); - } - delete obj; - - registeredObjects--; -} - -// -//void wiBULLET::soundTickCallback(btDynamicsWorld *world, btScalar timeStep) { -// int numManifolds = world->getDispatcher()->getNumManifolds(); -// for (int i=0;igetDispatcher()->getManifoldByIndexInternal(i); -// btCollisionObject* obA = (btCollisionObject*)(contactManifold->getBody0()); -// btCollisionObject* obB = (btCollisionObject*)(contactManifold->getBody1()); -// -// int numContacts = contactManifold->getNumContacts(); -// for (int j=0;jgetContactPoint(j); -// if (pt.getDistance()<0.f) -// { -// if(pt.getAppliedImpulse()>10.f){ -// //TODO: play some sound -// } -// const btVector3& ptA = pt.getPositionWorldOnA(); -// const btVector3& ptB = pt.getPositionWorldOnB(); -// const btVector3& normalOnB = pt.m_normalWorldOnB; -// } -// } -// } -//} -// -//void wiBULLET::pickingPreTickCallback (btDynamicsWorld *world, btScalar timeStep) -//{ -//// world->getWorldUserInfo(); -//// -//// if(grab) -//// { -//// /*const int x=softDemo->m_lastmousepos[0]; -//// const int y=softDemo->m_lastmousepos[1]; -//// const btVector3 rayFrom=softDemo->getCameraPosition(); -//// const btVector3 rayTo=softDemo->getRayTo(x,y); -//// const btVector3 rayDir=(rayTo-rayFrom).normalized(); -//// const btVector3 N=(softDemo->getCameraTargetPosition()-softDemo->getCameraPosition()).normalized(); -//// const btScalar O=btDot(softDemo->m_impact,N);*/ -//// const btVector3 rayFrom=btVector3(grabRay.origin.x,grabRay.origin.y,grabRay.origin.z); -//// const btVector3 rayDir=btVector3(grabRay.direction.x,grabRay.direction.y,grabRay.direction.z); -//// //const btScalar den=btDot(N,rayDir); -//// //if((den*den)>0) -/////* { -//// const btScalar num=O-btDot(N,rayFrom); -//// const btScalar hit=num/den; -//// if((hit>0)&&(hit<1500)) -//// { -//// softDemo->m_goal=rayFrom+rayDir*hit; -//// } -//// }*/ -//// btVector3 delta=softDemo->m_goal-softDemo->m_node->m_x; -//// static const btScalar maxdrag=10; -//// if(delta.length2()>(maxdrag*maxdrag)) -//// { -//// delta=delta.normalized()*maxdrag; -//// } -//// softDemo->m_node->m_v+=delta/timeStep; -//// } -//// -//} -//void wiBULLET::setGrab(bool value, const RAY& ray){ -// grab=value; -// grabRay=ray; -//} diff --git a/WickedEngine/wiBULLET.h b/WickedEngine/wiBULLET.h deleted file mode 100644 index 9e588ca72..000000000 --- a/WickedEngine/wiBULLET.h +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once -#include "wiPHYSICS.h" - -struct BulletPhysicsWorld; - -struct RAY; - -class wiBULLET:public PHYSICS -{ -private: - BulletPhysicsWorld * bulletPhysics = nullptr; - - void deleteObject(int id); -public: - wiBULLET(); - ~wiBULLET(); - - virtual void setWind(const XMFLOAT3& wind) override; - - virtual void connectVerticesToSoftBody(wiSceneSystem::SoftBodyPhysicsComponent& physicscomponent, wiSceneSystem::MeshComponent& mesh) override; - virtual void connectSoftBodyToVertices(wiSceneSystem::SoftBodyPhysicsComponent& physicscomponent, wiSceneSystem::MeshComponent& mesh) override; - virtual void transformBody(const XMFLOAT4& rot, const XMFLOAT3& pos, int objectI) override; - - virtual PhysicsTransform* getObject(int index) override; - - virtual void addRigidBody(wiSceneSystem::RigidBodyPhysicsComponent& physicscomponent, wiSceneSystem::MeshComponent& mesh, wiSceneSystem::TransformComponent& transform) override; - virtual void addSoftBody(wiSceneSystem::SoftBodyPhysicsComponent& physicscomponent, wiSceneSystem::MeshComponent& mesh, wiSceneSystem::TransformComponent& transform) override; - - virtual void removeRigidBody(wiSceneSystem::RigidBodyPhysicsComponent& physicscomponent) override; - virtual void removeSoftBody(wiSceneSystem::SoftBodyPhysicsComponent& physicscomponent) override; - - virtual void Update(float dt) override; - virtual void ClearWorld() override; - virtual void CleanUp() override; - -}; - diff --git a/WickedEngine/wiInitializer.cpp b/WickedEngine/wiInitializer.cpp index 433e34605..28e49097c 100644 --- a/WickedEngine/wiInitializer.cpp +++ b/WickedEngine/wiInitializer.cpp @@ -11,6 +11,7 @@ #include "wiHelper.h" #include "wiWidget.h" #include "wiGPUSortLib.h" +#include "wiPhysics.h" using namespace std; @@ -32,6 +33,8 @@ namespace wiInitializer wiWidget::LoadShaders(); wiGPUSortLib::LoadShaders(); + wiPhysics::Initialize(); + if (FAILED(wiSoundEffect::Initialize()) || FAILED(wiMusic::Initialize())) { stringstream ss(""); @@ -39,4 +42,5 @@ namespace wiInitializer wiHelper::messageBox(ss.str()); } } + } \ No newline at end of file diff --git a/WickedEngine/wiPHYSICS.h b/WickedEngine/wiPHYSICS.h index 2d053a3a3..d934820b9 100644 --- a/WickedEngine/wiPHYSICS.h +++ b/WickedEngine/wiPHYSICS.h @@ -1,51 +1,19 @@ #pragma once -#include "CommonInclude.h" +#include "wiECS.h" #include "wiSceneSystem_Decl.h" -#include - -class PHYSICS +namespace wiPhysics { -public: - struct PhysicsTransform - { - XMFLOAT4 rotation; - XMFLOAT3 position; - PhysicsTransform() { - rotation = XMFLOAT4(0, 0, 0, 1); - position = XMFLOAT3(0, 0, 0); - } - PhysicsTransform(const XMFLOAT4& newRot, const XMFLOAT3& newPos) { - rotation = newRot; - position = newPos; - } - }; - static int softBodyIterationCount; - static bool rigidBodyPhysicsEnabled, softBodyPhysicsEnabled; -protected: - std::vector transforms; - bool firstRunWorld; - int registeredObjects; -public: - void FirstRunWorld() { firstRunWorld = true; } - void NextRunWorld() { firstRunWorld = false; } - int getObjectCount() { return registeredObjects + 1; } + void Initialize(); + void CleanUp(); - virtual void Update(float dt)=0; - virtual void ClearWorld()=0; - virtual void CleanUp()=0; - - virtual void setWind(const XMFLOAT3& wind)=0; - - virtual void connectVerticesToSoftBody(wiSceneSystem::SoftBodyPhysicsComponent& physicscomponent, wiSceneSystem::MeshComponent& mesh) = 0; - virtual void connectSoftBodyToVertices(wiSceneSystem::SoftBodyPhysicsComponent& physicscomponent, wiSceneSystem::MeshComponent& mesh) = 0; - virtual void transformBody(const XMFLOAT4& rot, const XMFLOAT3& pos, int objectI) = 0; - - virtual PhysicsTransform* getObject(int index)=0; - - virtual void addRigidBody(wiSceneSystem::RigidBodyPhysicsComponent& physicscomponent, wiSceneSystem::MeshComponent& mesh, wiSceneSystem::TransformComponent& transform) = 0; - virtual void addSoftBody(wiSceneSystem::SoftBodyPhysicsComponent& physicscomponent, wiSceneSystem::MeshComponent& mesh, wiSceneSystem::TransformComponent& transform) = 0; - - virtual void removeRigidBody(wiSceneSystem::RigidBodyPhysicsComponent& physicscomponent) = 0; - virtual void removeSoftBody(wiSceneSystem::SoftBodyPhysicsComponent& physicscomponent) = 0; -}; + void RunPhysicsUpdateSystem( + const wiSceneSystem::WeatherComponent& weather, + wiECS::ComponentManager& transforms, + wiECS::ComponentManager& meshes, + wiECS::ComponentManager& objects, + wiECS::ComponentManager& rigidbodies, + wiECS::ComponentManager& softbodies, + float dt + ); +} diff --git a/WickedEngine/wiPhysics_Bullet.cpp b/WickedEngine/wiPhysics_Bullet.cpp new file mode 100644 index 000000000..489616250 --- /dev/null +++ b/WickedEngine/wiPhysics_Bullet.cpp @@ -0,0 +1,466 @@ +#include "wiPhysics.h" +#include "wiSceneSystem.h" +#include "wiProfiler.h" + + +#include "btBulletDynamicsCommon.h" + +#include "LinearMath/btHashMap.h" +#include "BulletSoftBody/btSoftRigidDynamicsWorld.h" +#include "BulletSoftBody/btSoftBodyHelpers.h" + +#include "BulletSoftBody/btSoftBodySolvers.h" +#include "BulletSoftBody/btDefaultSoftBodySolver.h" +#include "BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h" + +#include + +using namespace std; +using namespace wiECS; +using namespace wiSceneSystem; + +namespace wiPhysics +{ + btVector3 gravity(0, -11, 0); + int softbodyIterationCount = 5; + btCollisionConfiguration* collisionConfiguration = nullptr; + btCollisionDispatcher* dispatcher = nullptr; + btBroadphaseInterface* overlappingPairCache = nullptr; + btSequentialImpulseConstraintSolver* solver = nullptr; + btDynamicsWorld* dynamicsWorld = nullptr; + + btSoftBodySolver* softBodySolver = nullptr; + btSoftBodySolverOutput* softBodySolverOutput = nullptr; + + + unordered_map lookup; + + + void Initialize() + { + // collision configuration contains default setup for memory, collision setup. Advanced users can create their own configuration. + collisionConfiguration = new btSoftBodyRigidBodyCollisionConfiguration(); + + // use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded) + dispatcher = new btCollisionDispatcher(collisionConfiguration); + + // btDbvtBroadphase is a good general purpose broadphase. You can also try out btAxis3Sweep. + overlappingPairCache = new btDbvtBroadphase(); + + // the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded) + solver = new btSequentialImpulseConstraintSolver; + + //dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,overlappingPairCache,solver,collisionConfiguration); + dynamicsWorld = new btSoftRigidDynamicsWorld(dispatcher, overlappingPairCache, solver, collisionConfiguration, softBodySolver); + + dynamicsWorld->getSolverInfo().m_solverMode |= SOLVER_RANDMIZE_ORDER; + dynamicsWorld->getDispatchInfo().m_enableSatConvex = true; + dynamicsWorld->getSolverInfo().m_splitImpulse = true; + + dynamicsWorld->setGravity(gravity); + + ((btSoftRigidDynamicsWorld*)dynamicsWorld)->getWorldInfo().air_density = (btScalar)0.0; + ((btSoftRigidDynamicsWorld*)dynamicsWorld)->getWorldInfo().water_density = 0; + ((btSoftRigidDynamicsWorld*)dynamicsWorld)->getWorldInfo().water_offset = 0; + ((btSoftRigidDynamicsWorld*)dynamicsWorld)->getWorldInfo().water_normal = btVector3(0, 0, 0); + ((btSoftRigidDynamicsWorld*)dynamicsWorld)->getWorldInfo().m_gravity.setValue(gravity.x(), gravity.y(), gravity.z()); + ((btSoftRigidDynamicsWorld*)dynamicsWorld)->getWorldInfo().m_sparsesdf.Initialize(); + + } + void CleanUp() + { + delete dynamicsWorld; + delete solver; + delete overlappingPairCache; + delete dispatcher; + delete collisionConfiguration; + } + + + void Remove(Entity entity) + { + auto it = lookup.find(entity); + if (it != lookup.end()) + { + int id = it->second; + lookup.erase(it); + + btCollisionObject* obj = dynamicsWorld->getCollisionObjectArray()[id]; + btRigidBody* body = btRigidBody::upcast(obj); + + if (body && body->getMotionState()) + { + delete body->getMotionState(); + } + while (dynamicsWorld->getNumConstraints()) + { + btTypedConstraint* pc = dynamicsWorld->getConstraint(0); + dynamicsWorld->removeConstraint(pc); + delete pc; + } + + btSoftBody* softBody = btSoftBody::upcast(obj); + if (softBody) + { + ((btSoftRigidDynamicsWorld*)dynamicsWorld)->removeSoftBody(softBody); + } + else + { + btRigidBody* body = btRigidBody::upcast(obj); + if (body) + dynamicsWorld->removeRigidBody(body); + else + dynamicsWorld->removeCollisionObject(obj); + } + + delete obj; + } + } + int AddRigidBody(Entity entity, wiSceneSystem::RigidBodyPhysicsComponent& physicscomponent, const wiSceneSystem::MeshComponent& mesh, const wiSceneSystem::TransformComponent& transform) + { + btVector3 S(transform.scale_local.x, transform.scale_local.y, transform.scale_local.z); + + btCollisionShape* shape = nullptr; + + switch (physicscomponent.shape) + { + case RigidBodyPhysicsComponent::CollisionShape::BOX: + shape = new btBoxShape(S); + break; + + case RigidBodyPhysicsComponent::CollisionShape::SPHERE: + shape = new btSphereShape(btScalar(S.x())); + break; + + case RigidBodyPhysicsComponent::CollisionShape::CAPSULE: + shape = new btCapsuleShape(btScalar(S.x()), btScalar(S.y())); + break; + + case RigidBodyPhysicsComponent::CollisionShape::CONVEX_HULL: + { + shape = new btConvexHullShape(); + for (auto& pos : mesh.vertex_positions) + { + ((btConvexHullShape*)shape)->addPoint(btVector3(pos.x, pos.y, pos.z)); + } + shape->setLocalScaling(S); + } + break; + + case RigidBodyPhysicsComponent::CollisionShape::TRIANGLE_MESH: + { + int totalVerts = (int)mesh.vertex_positions.size(); + int totalTriangles = (int)mesh.indices.size() / 3; + + btVector3* btVerts = new btVector3[totalVerts]; + size_t i = 0; + for (auto& pos : mesh.vertex_positions) + { + btVerts[i++] = btVector3(pos.x, pos.y, pos.z); + } + + int* btInd = new int[mesh.indices.size()]; + i = 0; + for (auto& ind : mesh.indices) + { + btInd[i++] = ind; + } + + int vertStride = sizeof(btVector3); + int indexStride = 3 * sizeof(int); + + btTriangleIndexVertexArray* indexVertexArrays = new btTriangleIndexVertexArray( + totalTriangles, + btInd, + indexStride, + totalVerts, + (btScalar*)&btVerts[0].x(), + vertStride + ); + + bool useQuantizedAabbCompression = true; + shape = new btBvhTriangleMeshShape(indexVertexArrays, useQuantizedAabbCompression); + shape->setLocalScaling(S); + } + break; + } + + if (shape != nullptr) + { + shape->setMargin(btScalar(0.05)); + + btScalar mass(physicscomponent.mass); + + bool isDynamic = (mass != 0.f && !physicscomponent.IsKinematic()); + + btVector3 localInertia(0, 0, 0); + if (isDynamic) + { + shape->calculateLocalInertia(mass, localInertia); + } + else + { + mass = 0; + } + + //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects + btTransform shapeTransform; + shapeTransform.setIdentity(); + shapeTransform.setOrigin(btVector3(transform.translation_local.x, transform.translation_local.y, transform.translation_local.z)); + shapeTransform.setRotation(btQuaternion(transform.rotation_local.x, transform.rotation_local.y, transform.rotation_local.z, transform.rotation_local.w)); + btDefaultMotionState* myMotionState = new btDefaultMotionState(shapeTransform); + + btRigidBody::btRigidBodyConstructionInfo rbInfo(mass, myMotionState, shape, localInertia); + rbInfo.m_friction = physicscomponent.friction; + rbInfo.m_restitution = physicscomponent.restitution; + rbInfo.m_linearDamping = physicscomponent.damping; + rbInfo.m_angularDamping = physicscomponent.damping; + + btRigidBody* body = new btRigidBody(rbInfo); + if (physicscomponent.IsKinematic()) + { + body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + } + if (physicscomponent.IsDisableDeactivation()) + { + body->setActivationState(DISABLE_DEACTIVATION); + } + + int id = dynamicsWorld->getCollisionObjectArray().size(); + lookup[entity] = id; + dynamicsWorld->addRigidBody(body); + return id; + } + + return -1; + } + int AddSoftBody(Entity entity, wiSceneSystem::SoftBodyPhysicsComponent& physicscomponent, const wiSceneSystem::MeshComponent& mesh, const wiSceneSystem::TransformComponent& transform) + { + btVector3 S = btVector3(transform.scale_local.x, transform.scale_local.y, transform.scale_local.z); + btQuaternion R = btQuaternion(transform.rotation_local.x, transform.rotation_local.y, transform.rotation_local.z, transform.rotation_local.z); + btVector3 T = btVector3(transform.translation_local.x, transform.translation_local.y, transform.translation_local.z); + + const int vCount = (int)physicscomponent.physicsvertices.size(); + btScalar* btVerts = new btScalar[vCount * 3]; + for (int i = 0; i < vCount * 3; i += 3) { + const int vindex = i / 3; + btVerts[i] = btScalar(physicscomponent.physicsvertices[vindex].x); + btVerts[i + 1] = btScalar(physicscomponent.physicsvertices[vindex].y); + btVerts[i + 2] = btScalar(physicscomponent.physicsvertices[vindex].z); + } + const int iCount = (int)physicscomponent.physicsindices.size(); + const int tCount = iCount / 3; + int* btInd = new int[iCount]; + for (int i = 0; i < iCount; ++i) { + btInd[i] = physicscomponent.physicsindices[i]; + } + + + btSoftBody* softBody = btSoftBodyHelpers::CreateFromTriMesh( + ((btSoftRigidDynamicsWorld*)dynamicsWorld)->getWorldInfo() + , &btVerts[0] + , &btInd[0] + , tCount + , false + ); + + + delete[] btVerts; + delete[] btInd; + + if (softBody) + { + btSoftBody::Material* pm = softBody->appendMaterial(); + pm->m_kLST = 0.5; + pm->m_kVST = 0.5; + pm->m_kAST = 0.5; + pm->m_flags = 0; + softBody->generateBendingConstraints(2, pm); + softBody->randomizeConstraints(); + + btTransform shapeTransform; + shapeTransform.setIdentity(); + shapeTransform.setOrigin(T); + shapeTransform.setRotation(R); + softBody->scale(S); + softBody->transform(shapeTransform); + + + softBody->m_cfg.piterations = softbodyIterationCount; + softBody->m_cfg.aeromodel = btSoftBody::eAeroModel::F_TwoSidedLiftDrag; + + softBody->m_cfg.kAHR = btScalar(.69); //0.69 Anchor hardness [0,1] + softBody->m_cfg.kCHR = btScalar(1.0); //1 Rigid contact hardness [0,1] + softBody->m_cfg.kDF = btScalar(physicscomponent.friction); //0.2 Dynamic friction coefficient [0,1] + softBody->m_cfg.kDG = btScalar(0.01); //0 Drag coefficient [0,+inf] + softBody->m_cfg.kDP = btScalar(0.0); //0 Damping coefficient [0,1] + softBody->m_cfg.kKHR = btScalar(0.1); //0.1 Kinetic contact hardness [0,1] + softBody->m_cfg.kLF = btScalar(0.1); //0 Lift coefficient [0,+inf] + softBody->m_cfg.kMT = btScalar(0.0); //0 Pose matching coefficient [0,1] + softBody->m_cfg.kPR = btScalar(0.0); //0 Pressure coefficient [-1,1] + softBody->m_cfg.kSHR = btScalar(1.0); //1 Soft contacts hardness [0,1] + softBody->m_cfg.kVC = btScalar(0.0); //0 Volume conseration coefficient [0,+inf] + softBody->m_cfg.kVCF = btScalar(1.0); //1 Velocities correction factor (Baumgarte) + + softBody->m_cfg.kSKHR_CL = btScalar(1.0); //1 Soft vs. kinetic hardness [0,1] + softBody->m_cfg.kSK_SPLT_CL = btScalar(0.5); //0.5 Soft vs. rigid impulse split [0,1] + softBody->m_cfg.kSRHR_CL = btScalar(0.1); //0.1 Soft vs. rigid hardness [0,1] + softBody->m_cfg.kSR_SPLT_CL = btScalar(0.5); //0.5 Soft vs. rigid impulse split [0,1] + softBody->m_cfg.kSSHR_CL = btScalar(0.5); //0.5 Soft vs. soft hardness [0,1] + softBody->m_cfg.kSS_SPLT_CL = btScalar(0.5); //0.5 Soft vs. rigid impulse split [0,1] + + + btScalar mass = btScalar(physicscomponent.mass); + softBody->setTotalMass(mass); + + //int mvg = physicscomponent.massVG; + //if (mvg >= 0) { + // for (auto it = mesh.vertexGroups[mvg].vertex_weights.begin(); it != mesh.vertexGroups[mvg].vertex_weights.end(); ++it) { + // int vi = (*it).first; + // float wei = (*it).second; + // int index = physicscomponent.physicalmapGP[vi]; + // softBody->setMass(index, softBody->getMass(index)*btScalar(wei)); + // } + //} + + + //int gvg = physicscomponent.goalVG; + //if (gvg >= 0) { + // for (auto it = mesh.vertexGroups[gvg].vertex_weights.begin(); it != mesh.vertexGroups[gvg].vertex_weights.end(); ++it) { + // int vi = (*it).first; + // int index = physicscomponent.physicalmapGP[vi]; + // float weight = (*it).second; + // if (weight == 1) + // softBody->setMass(index, 0); + // } + //} + + softBody->getCollisionShape()->setMargin(btScalar(0.2)); + + //softBody->setWindVelocity(wind); + + softBody->setPose(true, true); + + softBody->setActivationState(DISABLE_DEACTIVATION); + + int id = dynamicsWorld->getCollisionObjectArray().size(); + lookup[entity] = id; + ((btSoftRigidDynamicsWorld*)dynamicsWorld)->addSoftBody(softBody); + return id; + } + + return -1; + } + + void RunPhysicsUpdateSystem( + const WeatherComponent& weather, + ComponentManager& transforms, + ComponentManager& meshes, + ComponentManager& objects, + ComponentManager& rigidbodies, + ComponentManager& softbodies, + float dt + ) + { + wiProfiler::GetInstance().BeginRange("Physics", wiProfiler::DOMAIN_CPU); + + btVector3 wind = btVector3(weather.windDirection.x, weather.windDirection.y, weather.windDirection.z); + + + // Rigid bodies - Objects: + for (size_t i = 0; i < rigidbodies.GetCount(); ++i) + { + Entity entity = rigidbodies.GetEntity(i); + RigidBodyPhysicsComponent& rigidbody = rigidbodies[i]; + TransformComponent& transform = *transforms.GetComponent(entity); + int id = -1; + + auto it = lookup.find(entity); + if (it == lookup.end()) + { + const ObjectComponent& object = *objects.GetComponent(entity); + const MeshComponent& mesh = *meshes.GetComponent(object.meshID); + id = AddRigidBody(entity, rigidbody, mesh, transform); + } + else + { + id = it->second; + } + assert(id >= 0 && id <= dynamicsWorld->getCollisionObjectArray().size()); + + btCollisionObject* obj = dynamicsWorld->getCollisionObjectArray()[id]; + btRigidBody* body = btRigidBody::upcast(obj); + + if (body != nullptr) + { + btMotionState* motionState = body->getMotionState(); + btTransform physicsTransform; + + if (rigidbody.IsKinematic()) + { + btVector3 T(transform.translation_local.x, transform.translation_local.y, transform.translation_local.z); + btQuaternion R(transform.rotation_local.x, transform.rotation_local.y, transform.rotation_local.z, transform.rotation_local.w); + physicsTransform.setOrigin(T); + physicsTransform.setRotation(R); + motionState->setWorldTransform(physicsTransform); + } + else + { + motionState->getWorldTransform(physicsTransform); + btVector3 T = physicsTransform.getOrigin(); + btQuaternion R = physicsTransform.getRotation(); + + transform.translation_local = XMFLOAT3(T.x(), T.y(), T.z()); + transform.rotation_local = XMFLOAT4(R.x(), R.y(), R.z(), R.w()); + transform.SetDirty(); + } + } + + + } + + // Soft bodies - Meshes: + for (size_t i = 0; i < softbodies.GetCount(); ++i) + { + Entity entity = softbodies.GetEntity(i); + SoftBodyPhysicsComponent& softbody = softbodies[i]; + MeshComponent& mesh = *meshes.GetComponent(entity); + mesh.SetDynamic(true); + int id = -1; + + auto it = lookup.find(entity); + if (it == lookup.end()) + { + TransformComponent transform; + id = AddSoftBody(entity, softbody, mesh, transform); + } + else + { + id = it->second; + } + assert(id >= 0 && id <= dynamicsWorld->getCollisionObjectArray().size()); + + } + + // Tidy: + for (auto it : lookup) + { + Entity entity = it.first; + bool exists = rigidbodies.Contains(entity); + if (!exists) + { + exists = softbodies.Contains(entity); + } + + if (!exists) + { + Remove(entity); + break; + } + } + + dynamicsWorld->stepSimulation(dt, 6); + + wiProfiler::GetInstance().EndRange(); // Physics + } +} diff --git a/WickedEngine/wiSceneSystem.cpp b/WickedEngine/wiSceneSystem.cpp index b25dffa6a..f7919b5fb 100644 --- a/WickedEngine/wiSceneSystem.cpp +++ b/WickedEngine/wiSceneSystem.cpp @@ -4,6 +4,7 @@ #include "wiResourceManager.h" #include "wiPHYSICS.h" #include "wiArchive.h" +#include "wiPhysics.h" using namespace wiECS; using namespace wiGraphicsTypes; @@ -814,7 +815,7 @@ namespace wiSceneSystem RunAnimationUpdateSystem(animations, transforms, dt); - RunPhysicsUpdateSystem(transforms, meshes, objects, rigidbodies, softbodies, dt); + wiPhysics::RunPhysicsUpdateSystem(weather, transforms, meshes, objects, rigidbodies, softbodies, dt); RunTransformUpdateSystem(transforms); @@ -1410,57 +1411,6 @@ namespace wiSceneSystem animation.timer = min(animation.timer, animationLength); } } - void RunPhysicsUpdateSystem( - ComponentManager& transforms, - ComponentManager& meshes, - ComponentManager& objects, - ComponentManager& rigidbodies, - ComponentManager& softbodies, - float dt - ) - { - //PHYSICS* physicsEngine = wiRenderer::physicsEngine; - - //if (physicsEngine != nullptr) - //{ - // physicsEngine->Update(dt); - - // // Rigid bodies - Objects: - // for (size_t i = 0; i < rigidbodies.GetCount(); ++i) - // { - // RigidBodyPhysicsComponent& rigidbody = rigidbodies[i]; - // Entity entity = rigidbodies.GetEntity(i); - // TransformComponent& transform = *transforms.GetComponent(entity); - - // if (rigidbody.kinematic) - // { - // //physicsEngine->transformBody(transform.rotation, transform.translation, rigidbody.physicsObjectID); - // } - // else - // { - // PHYSICS::PhysicsTransform* pt = physicsEngine->getObject(rigidbody.physicsObjectID); - // transform.translation_local = pt->position; - // transform.rotation_local = pt->rotation; - // transform.SetDirty(); - // } - - // } - - // // Soft bodies - Meshes: - // for (size_t i = 0; i < softbodies.GetCount(); ++i) - // { - // SoftBodyPhysicsComponent& softbody = softbodies[i]; - // Entity entity = softbodies.GetEntity(i); - - // MeshComponent& mesh = *meshes.GetComponent(entity); - // mesh.SetDynamic(true); - - // } - - // physicsEngine->NextRunWorld(); - //} - - } void RunTransformUpdateSystem(ComponentManager& transforms) { for (size_t i = 0; i < transforms.GetCount(); ++i) diff --git a/WickedEngine/wiSceneSystem.h b/WickedEngine/wiSceneSystem.h index bf3cdd799..ba4996a22 100644 --- a/WickedEngine/wiSceneSystem.h +++ b/WickedEngine/wiSceneSystem.h @@ -435,14 +435,16 @@ namespace wiSceneSystem ENUM_FORCE_UINT32 = 0xFFFFFFFF }; CollisionShape shape; - bool kinematic = false; float mass = 1.0f; float friction = 1.0f; float restitution = 1.0f; float damping = 1.0f; - // Non-serialized attributes: - int physicsObjectID = -1; + inline void SetDisableDeactivation(bool value) { if (value) { _flags |= DISABLE_DEACTIVATION; } else { _flags &= ~DISABLE_DEACTIVATION; } } + inline void SetKinematic(bool value) { if (value) { _flags |= KINEMATIC; } else { _flags &= ~KINEMATIC; } } + + inline bool IsDisableDeactivation() const { return _flags & DISABLE_DEACTIVATION; } + inline bool IsKinematic() const { return _flags & KINEMATIC; } void Serialize(wiArchive& archive, uint32_t seed = 0); }; @@ -461,9 +463,6 @@ namespace wiSceneSystem std::vector physicsvertices; std::vector physicsindices; - // Non-serialized attributes: - int physicsObjectID = -1; - void Serialize(wiArchive& archive, uint32_t seed = 0); }; @@ -989,14 +988,6 @@ namespace wiSceneSystem wiECS::ComponentManager& transforms, float dt ); - void RunPhysicsUpdateSystem( - wiECS::ComponentManager& transforms, - wiECS::ComponentManager& meshes, - wiECS::ComponentManager& objects, - wiECS::ComponentManager& rigidbodies, - wiECS::ComponentManager& softbodies, - float dt - ); void RunTransformUpdateSystem(wiECS::ComponentManager& transforms); void RunHierarchyUpdateSystem( const wiECS::ComponentManager& hierarchy, diff --git a/WickedEngine/wiSceneSystem_Serializers.cpp b/WickedEngine/wiSceneSystem_Serializers.cpp index 488665003..8dddd5be6 100644 --- a/WickedEngine/wiSceneSystem_Serializers.cpp +++ b/WickedEngine/wiSceneSystem_Serializers.cpp @@ -229,7 +229,6 @@ namespace wiSceneSystem { archive >> _flags; archive >> (uint32_t&)shape; - archive >> kinematic; archive >> mass; archive >> friction; archive >> restitution; @@ -239,7 +238,6 @@ namespace wiSceneSystem { archive << _flags; archive << (uint32_t&)shape; - archive << kinematic; archive << mass; archive << friction; archive << restitution;