From 4235c61fcf4218ae9310634549b5490e536b4e57 Mon Sep 17 00:00:00 2001 From: erwincoumans Date: Mon, 7 Nov 2016 12:08:02 -0800 Subject: [PATCH] move CommonRigidBodyMTBase out of interfaces, into MultiThreadedDemo. --- examples/Benchmarks/BenchmarkDemo.cpp | 10 +- .../CommonInterfaces/CommonRigidBodyBase.h | 49 +- examples/ExampleBrowser/CMakeLists.txt | 4 +- examples/ExampleBrowser/premake4.lua | 2 +- .../CommonRigidBodyMTBase.cpp} | 19 +- .../MultiThreadedDemo/CommonRigidBodyMTBase.h | 427 ++++++++++++++++++ .../MultiThreadedDemo/MultiThreadedDemo.cpp | 14 +- .../ParallelFor.h | 0 8 files changed, 489 insertions(+), 36 deletions(-) rename examples/{CommonInterfaces/CommonRigidBodyBase.cpp => MultiThreadedDemo/CommonRigidBodyMTBase.cpp} (98%) create mode 100644 examples/MultiThreadedDemo/CommonRigidBodyMTBase.h rename examples/{CommonInterfaces => MultiThreadedDemo}/ParallelFor.h (100%) diff --git a/examples/Benchmarks/BenchmarkDemo.cpp b/examples/Benchmarks/BenchmarkDemo.cpp index 0eee37149..00ac36b9c 100644 --- a/examples/Benchmarks/BenchmarkDemo.cpp +++ b/examples/Benchmarks/BenchmarkDemo.cpp @@ -32,7 +32,7 @@ subject to the following restrictions: #include "LinearMath/btAlignedObjectArray.h" #include "LinearMath/btTransform.h" -#include "../CommonInterfaces/ParallelFor.h" +#include "../MultiThreadedDemo/ParallelFor.h" class btDynamicsWorld; @@ -49,11 +49,11 @@ struct btCollisionAlgorithmCreateFunc; class btDefaultCollisionConfiguration; -#include "../CommonInterfaces/CommonRigidBodyBase.h" +#include "../MultiThreadedDemo/CommonRigidBodyMTBase.h" -class BenchmarkDemo : public CommonRigidBodyBase +class BenchmarkDemo : public CommonRigidBodyMTBase { //keep the collision shapes, for deletion/cleanup @@ -93,7 +93,7 @@ class BenchmarkDemo : public CommonRigidBodyBase public: BenchmarkDemo(struct GUIHelperInterface* helper, int benchmark) - :CommonRigidBodyBase(helper), + :CommonRigidBodyMTBase(helper), m_benchmark(benchmark) { } @@ -1296,7 +1296,7 @@ void BenchmarkDemo::exitPhysics() } m_ragdolls.clear(); - CommonRigidBodyBase::exitPhysics(); + CommonRigidBodyMTBase::exitPhysics(); } diff --git a/examples/CommonInterfaces/CommonRigidBodyBase.h b/examples/CommonInterfaces/CommonRigidBodyBase.h index cfbd0053a..07175ca25 100644 --- a/examples/CommonInterfaces/CommonRigidBodyBase.h +++ b/examples/CommonInterfaces/CommonRigidBodyBase.h @@ -21,8 +21,6 @@ struct CommonRigidBodyBase : public CommonExampleInterface btConstraintSolver* m_solver; btDefaultCollisionConfiguration* m_collisionConfiguration; btDiscreteDynamicsWorld* m_dynamicsWorld; - bool m_multithreadedWorld; - bool m_multithreadCapable; //data for picking objects class btRigidBody* m_pickedBody; @@ -33,8 +31,20 @@ struct CommonRigidBodyBase : public CommonExampleInterface btScalar m_oldPickingDist; struct GUIHelperInterface* m_guiHelper; - CommonRigidBodyBase(struct GUIHelperInterface* helper); - virtual ~CommonRigidBodyBase(); + CommonRigidBodyBase(struct GUIHelperInterface* helper) + :m_broadphase(0), + m_dispatcher(0), + m_solver(0), + m_collisionConfiguration(0), + m_dynamicsWorld(0), + m_pickedBody(0), + m_pickedConstraint(0), + m_guiHelper(helper) + { + } + virtual ~CommonRigidBodyBase() + { + } btDiscreteDynamicsWorld* getDynamicsWorld() @@ -42,8 +52,26 @@ struct CommonRigidBodyBase : public CommonExampleInterface return m_dynamicsWorld; } - virtual void createDefaultParameters(); - virtual void createEmptyDynamicsWorld(); + virtual void createEmptyDynamicsWorld() + { + ///collision configuration contains default setup for memory, collision setup + m_collisionConfiguration = new btDefaultCollisionConfiguration(); + //m_collisionConfiguration->setConvexConvexMultipointIterations(); + + ///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded) + m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); + + m_broadphase = new btDbvtBroadphase(); + + ///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded) + btSequentialImpulseConstraintSolver* sol = new btSequentialImpulseConstraintSolver; + m_solver = sol; + + m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher, m_broadphase, m_solver, m_collisionConfiguration); + + m_dynamicsWorld->setGravity(btVector3(0, -10, 0)); + } + virtual void stepSimulation(float deltaTime) { @@ -53,7 +81,14 @@ struct CommonRigidBodyBase : public CommonExampleInterface } } - virtual void physicsDebugDraw(int debugFlags); + virtual void physicsDebugDraw(int debugFlags) + { + if (m_dynamicsWorld && m_dynamicsWorld->getDebugDrawer()) + { + m_dynamicsWorld->getDebugDrawer()->setDebugMode(debugFlags); + m_dynamicsWorld->debugDrawWorld(); + } + } virtual void exitPhysics() { diff --git a/examples/ExampleBrowser/CMakeLists.txt b/examples/ExampleBrowser/CMakeLists.txt index dcdf76878..0096560b6 100644 --- a/examples/ExampleBrowser/CMakeLists.txt +++ b/examples/ExampleBrowser/CMakeLists.txt @@ -32,7 +32,6 @@ ADD_LIBRARY(BulletExampleBrowserLib GL_ShapeDrawer.cpp CollisionShape2TriangleMesh.cpp CollisionShape2TriangleMesh.h - ../CommonInterfaces/CommonRigidBodyBase.cpp ../Utils/b3Clock.cpp ../Utils/b3Clock.h ../Utils/b3ResourcePath.cpp @@ -200,6 +199,9 @@ SET(BulletExampleBrowser_SRCS ../ForkLift/ForkLiftDemo.h ../MultiThreadedDemo/MultiThreadedDemo.cpp ../MultiThreadedDemo/MultiThreadedDemo.h + ../MultiThreadedDemo/CommonRigidBodyMTBase.cpp + ../MultiThreadedDemo/CommonRigidBodyMTBase.h + ../MultiThreadedDemo/ParallelFor.h ../Tutorial/Tutorial.cpp ../Tutorial/Tutorial.h ../Tutorial/Dof6ConstraintTutorial.cpp diff --git a/examples/ExampleBrowser/premake4.lua b/examples/ExampleBrowser/premake4.lua index f99968f99..ac184dedc 100644 --- a/examples/ExampleBrowser/premake4.lua +++ b/examples/ExampleBrowser/premake4.lua @@ -104,7 +104,7 @@ project "App_BulletExampleBrowser" "../Collision/Internal/*", "../Benchmarks/*", "../MultiThreadedDemo/*", - "../CommonInterfaces/*", + "../CommonInterfaces/*.h", "../ForkLift/ForkLiftDemo.*", "../Importers/**", "../../Extras/Serialize/BulletWorldImporter/*", diff --git a/examples/CommonInterfaces/CommonRigidBodyBase.cpp b/examples/MultiThreadedDemo/CommonRigidBodyMTBase.cpp similarity index 98% rename from examples/CommonInterfaces/CommonRigidBodyBase.cpp rename to examples/MultiThreadedDemo/CommonRigidBodyMTBase.cpp index 9ae25c9ed..6edada4de 100644 --- a/examples/CommonInterfaces/CommonRigidBodyBase.cpp +++ b/examples/MultiThreadedDemo/CommonRigidBodyMTBase.cpp @@ -21,13 +21,8 @@ subject to the following restrictions: class btCollisionShape; -#include "CommonExampleInterface.h" -#include "CommonRigidBodyBase.h" -#include "CommonParameterInterface.h" -#include "CommonGUIHelperInterface.h" -#include "CommonRenderInterface.h" -#include "CommonWindowInterface.h" -#include "CommonGraphicsAppInterface.h" +#include "CommonRigidBodyMTBase.h" +#include "../CommonInterfaces/CommonParameterInterface.h" #include "ParallelFor.h" #include "LinearMath/btAlignedObjectArray.h" #include "LinearMath/btPoolAllocator.h" @@ -597,7 +592,7 @@ static bool gDisplayProfileInfo = false; static btScalar gSliderNumThreads = 1.0f; // should be int //////////////////////////////////// -CommonRigidBodyBase::CommonRigidBodyBase( struct GUIHelperInterface* helper ) +CommonRigidBodyMTBase::CommonRigidBodyMTBase( struct GUIHelperInterface* helper ) :m_broadphase( 0 ), m_dispatcher( 0 ), m_solver( 0 ), @@ -612,7 +607,7 @@ CommonRigidBodyBase::CommonRigidBodyBase( struct GUIHelperInterface* helper ) gTaskMgr.init(); } -CommonRigidBodyBase::~CommonRigidBodyBase() +CommonRigidBodyMTBase::~CommonRigidBodyMTBase() { gTaskMgr.shutdown(); } @@ -651,7 +646,7 @@ void setThreadCountCallback(float val) } } -void CommonRigidBodyBase::createEmptyDynamicsWorld() +void CommonRigidBodyMTBase::createEmptyDynamicsWorld() { gNumIslands = 0; #if BT_THREADSAFE && (BT_USE_OPENMP || BT_USE_PPL || BT_USE_TBB) @@ -716,7 +711,7 @@ void CommonRigidBodyBase::createEmptyDynamicsWorld() } -void CommonRigidBodyBase::createDefaultParameters() +void CommonRigidBodyMTBase::createDefaultParameters() { if (m_multithreadCapable) { @@ -761,7 +756,7 @@ void CommonRigidBodyBase::createDefaultParameters() } } -void CommonRigidBodyBase::physicsDebugDraw(int debugFlags) +void CommonRigidBodyMTBase::physicsDebugDraw(int debugFlags) { if (m_dynamicsWorld && m_dynamicsWorld->getDebugDrawer()) { diff --git a/examples/MultiThreadedDemo/CommonRigidBodyMTBase.h b/examples/MultiThreadedDemo/CommonRigidBodyMTBase.h new file mode 100644 index 000000000..d4e291011 --- /dev/null +++ b/examples/MultiThreadedDemo/CommonRigidBodyMTBase.h @@ -0,0 +1,427 @@ + +#ifndef COMMON_RIGID_BODY_MT_BASE_H +#define COMMON_RIGID_BODY_MT_BASE_H + + +#include "btBulletDynamicsCommon.h" +#include "../CommonInterfaces/CommonExampleInterface.h" +#include "../CommonInterfaces/CommonGUIHelperInterface.h" +#include "../CommonInterfaces/CommonRenderInterface.h" +#include "../CommonInterfaces/CommonCameraInterface.h" +#include "../CommonInterfaces/CommonGraphicsAppInterface.h" +#include "../CommonInterfaces/CommonWindowInterface.h" + +struct CommonRigidBodyMTBase : public CommonExampleInterface +{ + //keep the collision shapes, for deletion/cleanup + btAlignedObjectArray m_collisionShapes; + btBroadphaseInterface* m_broadphase; + btCollisionDispatcher* m_dispatcher; + btConstraintSolver* m_solver; + btDefaultCollisionConfiguration* m_collisionConfiguration; + btDiscreteDynamicsWorld* m_dynamicsWorld; + bool m_multithreadedWorld; + bool m_multithreadCapable; + + //data for picking objects + class btRigidBody* m_pickedBody; + class btTypedConstraint* m_pickedConstraint; + int m_savedState; + btVector3 m_oldPickingPos; + btVector3 m_hitPos; + btScalar m_oldPickingDist; + struct GUIHelperInterface* m_guiHelper; + + CommonRigidBodyMTBase(struct GUIHelperInterface* helper); + virtual ~CommonRigidBodyMTBase(); + + + btDiscreteDynamicsWorld* getDynamicsWorld() + { + return m_dynamicsWorld; + } + + virtual void createDefaultParameters(); + virtual void createEmptyDynamicsWorld(); + + virtual void stepSimulation(float deltaTime) + { + if (m_dynamicsWorld) + { + m_dynamicsWorld->stepSimulation(deltaTime); + } + } + + virtual void physicsDebugDraw(int debugFlags); + + virtual void exitPhysics() + { + removePickingConstraint(); + //cleanup in the reverse order of creation/initialization + + //remove the rigidbodies from the dynamics world and delete them + + if (m_dynamicsWorld) + { + + int i; + for (i = m_dynamicsWorld->getNumConstraints() - 1; i >= 0; i--) + { + m_dynamicsWorld->removeConstraint(m_dynamicsWorld->getConstraint(i)); + } + for (i = m_dynamicsWorld->getNumCollisionObjects() - 1; i >= 0; i--) + { + btCollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[i]; + btRigidBody* body = btRigidBody::upcast(obj); + if (body && body->getMotionState()) + { + delete body->getMotionState(); + } + m_dynamicsWorld->removeCollisionObject(obj); + delete obj; + } + } + //delete collision shapes + for (int j = 0; jgetDebugDrawer()) + { + m_dynamicsWorld->getDebugDrawer()->setDebugMode(debugDrawFlags); + } + m_dynamicsWorld->debugDrawWorld(); + } + + } + + virtual bool keyboardCallback(int key, int state) + { + if ((key==B3G_F3) && state && m_dynamicsWorld) + { + btDefaultSerializer* serializer = new btDefaultSerializer(); + m_dynamicsWorld->serialize(serializer); + + FILE* file = fopen("testFile.bullet","wb"); + fwrite(serializer->getBufferPointer(),serializer->getCurrentBufferSize(),1, file); + fclose(file); + //b3Printf("btDefaultSerializer wrote testFile.bullet"); + delete serializer; + return true; + + } + return false;//don't handle this key + } + + + btVector3 getRayTo(int x,int y) + { + CommonRenderInterface* renderer = m_guiHelper->getRenderInterface(); + + if (!renderer) + { + btAssert(0); + return btVector3(0,0,0); + } + + float top = 1.f; + float bottom = -1.f; + float nearPlane = 1.f; + float tanFov = (top-bottom)*0.5f / nearPlane; + float fov = btScalar(2.0) * btAtan(tanFov); + + btVector3 camPos,camTarget; + + renderer->getActiveCamera()->getCameraPosition(camPos); + renderer->getActiveCamera()->getCameraTargetPosition(camTarget); + + btVector3 rayFrom = camPos; + btVector3 rayForward = (camTarget-camPos); + rayForward.normalize(); + float farPlane = 10000.f; + rayForward*= farPlane; + + btVector3 rightOffset; + btVector3 cameraUp=btVector3(0,0,0); + cameraUp[m_guiHelper->getAppInterface()->getUpAxis()]=1; + + btVector3 vertical = cameraUp; + + btVector3 hor; + hor = rayForward.cross(vertical); + hor.safeNormalize(); + vertical = hor.cross(rayForward); + vertical.safeNormalize(); + + float tanfov = tanf(0.5f*fov); + + + hor *= 2.f * farPlane * tanfov; + vertical *= 2.f * farPlane * tanfov; + + btScalar aspect; + float width = float(renderer->getScreenWidth()); + float height = float (renderer->getScreenHeight()); + + aspect = width / height; + + hor*=aspect; + + + btVector3 rayToCenter = rayFrom + rayForward; + btVector3 dHor = hor * 1.f/width; + btVector3 dVert = vertical * 1.f/height; + + + btVector3 rayTo = rayToCenter - 0.5f * hor + 0.5f * vertical; + rayTo += btScalar(x) * dHor; + rayTo -= btScalar(y) * dVert; + return rayTo; + } + + virtual bool mouseMoveCallback(float x,float y) + { + CommonRenderInterface* renderer = m_guiHelper->getRenderInterface(); + + if (!renderer) + { + btAssert(0); + return false; + } + + btVector3 rayTo = getRayTo(int(x), int(y)); + btVector3 rayFrom; + renderer->getActiveCamera()->getCameraPosition(rayFrom); + movePickedBody(rayFrom,rayTo); + + return false; + } + + virtual bool mouseButtonCallback(int button, int state, float x, float y) + { + CommonRenderInterface* renderer = m_guiHelper->getRenderInterface(); + + if (!renderer) + { + btAssert(0); + return false; + } + + CommonWindowInterface* window = m_guiHelper->getAppInterface()->m_window; + +#if 0 + if (window->isModifierKeyPressed(B3G_ALT)) + { + printf("ALT pressed\n"); + } else + { + printf("NO ALT pressed\n"); + } + + if (window->isModifierKeyPressed(B3G_SHIFT)) + { + printf("SHIFT pressed\n"); + } else + { + printf("NO SHIFT pressed\n"); + } + + if (window->isModifierKeyPressed(B3G_CONTROL)) + { + printf("CONTROL pressed\n"); + } else + { + printf("NO CONTROL pressed\n"); + } +#endif + + + if (state==1) + { + if(button==0 && (!window->isModifierKeyPressed(B3G_ALT) && !window->isModifierKeyPressed(B3G_CONTROL) )) + { + btVector3 camPos; + renderer->getActiveCamera()->getCameraPosition(camPos); + + btVector3 rayFrom = camPos; + btVector3 rayTo = getRayTo(int(x),int(y)); + + pickBody(rayFrom, rayTo); + + + } + } else + { + if (button==0) + { + removePickingConstraint(); + //remove p2p + } + } + + //printf("button=%d, state=%d\n",button,state); + return false; + } + + + virtual bool pickBody(const btVector3& rayFromWorld, const btVector3& rayToWorld) + { + if (m_dynamicsWorld==0) + return false; + + btCollisionWorld::ClosestRayResultCallback rayCallback(rayFromWorld, rayToWorld); + + m_dynamicsWorld->rayTest(rayFromWorld, rayToWorld, rayCallback); + if (rayCallback.hasHit()) + { + + btVector3 pickPos = rayCallback.m_hitPointWorld; + btRigidBody* body = (btRigidBody*)btRigidBody::upcast(rayCallback.m_collisionObject); + if (body) + { + //other exclusions? + if (!(body->isStaticObject() || body->isKinematicObject())) + { + m_pickedBody = body; + m_savedState = m_pickedBody->getActivationState(); + m_pickedBody->setActivationState(DISABLE_DEACTIVATION); + //printf("pickPos=%f,%f,%f\n",pickPos.getX(),pickPos.getY(),pickPos.getZ()); + btVector3 localPivot = body->getCenterOfMassTransform().inverse() * pickPos; + btPoint2PointConstraint* p2p = new btPoint2PointConstraint(*body, localPivot); + m_dynamicsWorld->addConstraint(p2p, true); + m_pickedConstraint = p2p; + btScalar mousePickClamping = 30.f; + p2p->m_setting.m_impulseClamp = mousePickClamping; + //very weak constraint for picking + p2p->m_setting.m_tau = 0.001f; + } + } + + + // pickObject(pickPos, rayCallback.m_collisionObject); + m_oldPickingPos = rayToWorld; + m_hitPos = pickPos; + m_oldPickingDist = (pickPos - rayFromWorld).length(); + // printf("hit !\n"); + //add p2p + } + return false; + } + virtual bool movePickedBody(const btVector3& rayFromWorld, const btVector3& rayToWorld) + { + if (m_pickedBody && m_pickedConstraint) + { + btPoint2PointConstraint* pickCon = static_cast(m_pickedConstraint); + if (pickCon) + { + //keep it at the same picking distance + + btVector3 newPivotB; + + btVector3 dir = rayToWorld - rayFromWorld; + dir.normalize(); + dir *= m_oldPickingDist; + + newPivotB = rayFromWorld + dir; + pickCon->setPivotB(newPivotB); + return true; + } + } + return false; + } + virtual void removePickingConstraint() + { + if (m_pickedConstraint) + { + m_pickedBody->forceActivationState(m_savedState); + m_pickedBody->activate(); + m_dynamicsWorld->removeConstraint(m_pickedConstraint); + delete m_pickedConstraint; + m_pickedConstraint = 0; + m_pickedBody = 0; + } + } + + + + btBoxShape* createBoxShape(const btVector3& halfExtents) + { + btBoxShape* box = new btBoxShape(halfExtents); + return box; + } + + btRigidBody* createRigidBody(float mass, const btTransform& startTransform, btCollisionShape* shape, const btVector4& color = btVector4(1, 0, 0, 1)) + { + btAssert((!shape || shape->getShapeType() != INVALID_SHAPE_PROXYTYPE)); + + //rigidbody is dynamic if and only if mass is non zero, otherwise static + bool isDynamic = (mass != 0.f); + + btVector3 localInertia(0, 0, 0); + if (isDynamic) + shape->calculateLocalInertia(mass, localInertia); + + //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects + +#define USE_MOTIONSTATE 1 +#ifdef USE_MOTIONSTATE + btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform); + + btRigidBody::btRigidBodyConstructionInfo cInfo(mass, myMotionState, shape, localInertia); + + btRigidBody* body = new btRigidBody(cInfo); + //body->setContactProcessingThreshold(m_defaultContactProcessingThreshold); + +#else + btRigidBody* body = new btRigidBody(mass, 0, shape, localInertia); + body->setWorldTransform(startTransform); +#endif// + + body->setUserIndex(-1); + m_dynamicsWorld->addRigidBody(body); + return body; + } + + + + virtual void renderScene() + { + { + + m_guiHelper->syncPhysicsToGraphics(m_dynamicsWorld); + } + + { + + m_guiHelper->render(m_dynamicsWorld); + } + } +}; + +#endif //#define COMMON_RIGID_BODY_MT_BASE_H + + diff --git a/examples/MultiThreadedDemo/MultiThreadedDemo.cpp b/examples/MultiThreadedDemo/MultiThreadedDemo.cpp index 25c20383d..d07ef4ca2 100644 --- a/examples/MultiThreadedDemo/MultiThreadedDemo.cpp +++ b/examples/MultiThreadedDemo/MultiThreadedDemo.cpp @@ -16,19 +16,13 @@ subject to the following restrictions: #include "btBulletDynamicsCommon.h" #include "LinearMath/btQuickprof.h" #include "LinearMath/btIDebugDraw.h" - +#include "../CommonInterfaces/CommonParameterInterface.h" #include //printf debugging #include class btCollisionShape; -#include "../CommonInterfaces/CommonExampleInterface.h" -#include "../CommonInterfaces/CommonRigidBodyBase.h" -#include "../CommonInterfaces/CommonParameterInterface.h" -#include "../CommonInterfaces/CommonGUIHelperInterface.h" -#include "../CommonInterfaces/CommonRenderInterface.h" -#include "../CommonInterfaces/CommonWindowInterface.h" -#include "../CommonInterfaces/CommonGraphicsAppInterface.h" +#include "CommonRigidBodyMTBase.h" #include "MultiThreadedDemo.h" #include "LinearMath/btAlignedObjectArray.h" #include "btBulletCollisionCommon.h" @@ -37,7 +31,7 @@ class btCollisionShape; #define BT_OVERRIDE /// MultiThreadedDemo shows how to setup and use multithreading -class MultiThreadedDemo : public CommonRigidBodyBase +class MultiThreadedDemo : public CommonRigidBodyMTBase { static const int kUpAxis = 1; @@ -84,7 +78,7 @@ public: MultiThreadedDemo::MultiThreadedDemo(struct GUIHelperInterface* helper) - : CommonRigidBodyBase( helper ) + : CommonRigidBodyMTBase( helper ) { m_cameraTargetPos = btVector3( 0.0f, 0.0f, 0.0f ); m_cameraPitch = 90.0f; diff --git a/examples/CommonInterfaces/ParallelFor.h b/examples/MultiThreadedDemo/ParallelFor.h similarity index 100% rename from examples/CommonInterfaces/ParallelFor.h rename to examples/MultiThreadedDemo/ParallelFor.h