From 79be214d0839198b957224ecc9f31af331f11790 Mon Sep 17 00:00:00 2001 From: Benjamin Ellenberger Date: Sun, 15 May 2016 14:19:01 +0200 Subject: [PATCH 01/14] Merge resolve. --- examples/ExampleBrowser/CMakeLists.txt | 14 ++++++++++++++ examples/ExampleBrowser/ExampleEntries.cpp | 6 ++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/examples/ExampleBrowser/CMakeLists.txt b/examples/ExampleBrowser/CMakeLists.txt index 7dc6326b6..7931892df 100644 --- a/examples/ExampleBrowser/CMakeLists.txt +++ b/examples/ExampleBrowser/CMakeLists.txt @@ -156,6 +156,20 @@ SET(BulletExampleBrowser_SRCS ../Tutorial/Tutorial.h ../Tutorial/Dof6ConstraintTutorial.cpp ../Tutorial/Dof6ConstraintTutorial.h + ../ExtendedTutorials/SimpleBox.cpp + ../ExtendedTutorials/SimpleBox.h + ../ExtendedTutorials/MultipleBoxes.cpp + ../ExtendedTutorials/MultipleBoxes.h + ../ExtendedTutorials/SimpleCloth.cpp + ../ExtendedTutorials/SimpleCloth.h + ../ExtendedTutorials/SimpleJoint.cpp + ../ExtendedTutorials/SimpleJoint.h + ../ExtendedTutorials/NewtonianPendulum.cpp + ../ExtendedTutorials/NewtonianPendulum.h + ../ExtendedTutorials/InclinedPlane.cpp + ../ExtendedTutorials/InclinedPlane.h + ../ExtendedTutorials/MultiPendulum.cpp + ../ExtendedTutorials/MultiPendulum.h ../Collision/CollisionSdkC_Api.cpp ../Collision/CollisionSdkC_Api.h ../Collision/CollisionTutorialBullet2.cpp diff --git a/examples/ExampleBrowser/ExampleEntries.cpp b/examples/ExampleBrowser/ExampleEntries.cpp index 3ac486cd6..70645a901 100644 --- a/examples/ExampleBrowser/ExampleEntries.cpp +++ b/examples/ExampleBrowser/ExampleEntries.cpp @@ -45,7 +45,6 @@ #include "../Tutorial/Dof6ConstraintTutorial.h" #include "../MultiThreading/MultiThreadingExample.h" #include "../InverseDynamics/InverseDynamicsExample.h" - #ifdef ENABLE_LUA #include "../LuaDemo/LuaPhysicsSetup.h" #endif @@ -269,7 +268,10 @@ static ExampleEntry gDefaultExamples[]= ExampleEntry(1,"Simple Cloth", "Creating a simple piece of cloth", ET_SimpleClothCreateFunc), ExampleEntry(1,"Simple Chain", "Creating a simple chain using a pair of point2point/distance constraints. You may click and drag any box to see the chain respond.", ET_ChainCreateFunc), ExampleEntry(1,"Simple Bridge", "Creating a simple bridge using a pair of point2point/distance constraints. You may click and drag any plank to see the bridge respond.", ET_BridgeCreateFunc), - + ExampleEntry(1,"Inclined Plane","Drop some boxes on an inclined plane",ET_InclinedPlaneCreateFunc), + ExampleEntry(1,"Multi Pendulum","Create a multi pendulum",ET_MultiPendulumCreateFunc), + ExampleEntry(1,"Newtonian Pendulum","Create a newtonian pendulum",ET_NewtonianPendulumCreateFunc), + //todo: create a category/tutorial about advanced topics, such as optimizations, using different collision detection algorithm, different constraint solvers etc. //ExampleEntry(0,"Advanced"), //ExampleEntry(1,"Obj2RigidBody Add Features", "Load a triangle mesh from Wavefront .obj and create polyhedral features to perform the separating axis test (instead of GJK/MPR). It is best to combine optimization and polyhedral feature generation.", ET_RigidBodyFromObjCreateFunc,OptimizeConvexObj+ComputePolyhedralFeatures), From 9872d2b20ff79ad56d4632846ff0a17e3367c281 Mon Sep 17 00:00:00 2001 From: Benjamin Ellenberger Date: Sat, 4 Jun 2016 12:09:37 +0200 Subject: [PATCH 02/14] Create InclinedPlane,Newton's Cradle and Multi-Pendulum examples for the Bullet Example Browser. --- examples/ExampleBrowser/CMakeLists.txt | 9 +- examples/ExampleBrowser/ExampleEntries.cpp | 19 +- examples/ExtendedTutorials/InclinedPlane.cpp | 372 +++++++++++++++++ examples/ExtendedTutorials/InclinedPlane.h | 22 + examples/ExtendedTutorials/MultiPendulum.cpp | 418 +++++++++++++++++++ examples/ExtendedTutorials/MultiPendulum.h | 22 + examples/ExtendedTutorials/NewtonsCradle.cpp | 350 ++++++++++++++++ examples/ExtendedTutorials/NewtonsCradle.h | 22 + 8 files changed, 1225 insertions(+), 9 deletions(-) create mode 100644 examples/ExtendedTutorials/InclinedPlane.cpp create mode 100644 examples/ExtendedTutorials/InclinedPlane.h create mode 100644 examples/ExtendedTutorials/MultiPendulum.cpp create mode 100644 examples/ExtendedTutorials/MultiPendulum.h create mode 100644 examples/ExtendedTutorials/NewtonsCradle.cpp create mode 100644 examples/ExtendedTutorials/NewtonsCradle.h diff --git a/examples/ExampleBrowser/CMakeLists.txt b/examples/ExampleBrowser/CMakeLists.txt index 2129051c3..0af74fdb8 100644 --- a/examples/ExampleBrowser/CMakeLists.txt +++ b/examples/ExampleBrowser/CMakeLists.txt @@ -114,7 +114,10 @@ SET(ExtendedTutorialsSources ../ExtendedTutorials/SimpleCloth.cpp ../ExtendedTutorials/Chain.cpp ../ExtendedTutorials/Bridge.cpp - ../ExtendedTutorials/RigidBodyFromObj.cpp + ../ExtendedTutorials/RigidBodyFromObj.cpp + ../ExtendedTutorials/InclinedPlane.cpp + ../ExtendedTutorials/InclinedPlane.h + ../ExtendedTutorials/NewtonsCradle.cpp ) SET(BulletExampleBrowser_SRCS @@ -166,8 +169,8 @@ SET(BulletExampleBrowser_SRCS ../ExtendedTutorials/SimpleCloth.h ../ExtendedTutorials/SimpleJoint.cpp ../ExtendedTutorials/SimpleJoint.h - ../ExtendedTutorials/NewtonianPendulum.cpp - ../ExtendedTutorials/NewtonianPendulum.h + ../ExtendedTutorials/NewtonsCradle.cpp + ../ExtendedTutorials/NewtonsCradle.h ../ExtendedTutorials/InclinedPlane.cpp ../ExtendedTutorials/InclinedPlane.h ../ExtendedTutorials/MultiPendulum.cpp diff --git a/examples/ExampleBrowser/ExampleEntries.cpp b/examples/ExampleBrowser/ExampleEntries.cpp index 3f892b01b..10cfe33ee 100644 --- a/examples/ExampleBrowser/ExampleEntries.cpp +++ b/examples/ExampleBrowser/ExampleEntries.cpp @@ -56,7 +56,7 @@ #endif #endif //B3_USE_CLEW -//Extended Tutorial Includes Added by Mobeen +//Extended Tutorial Includes Added by Mobeen and Benelot #include "../ExtendedTutorials/SimpleBox.h" #include "../ExtendedTutorials/MultipleBoxes.h" #include "../ExtendedTutorials/SimpleJoint.h" @@ -64,6 +64,9 @@ #include "../ExtendedTutorials/Chain.h" #include "../ExtendedTutorials/Bridge.h" #include "../ExtendedTutorials/RigidBodyFromObj.h" +#include "../ExtendedTutorials/InclinedPlane.h" +#include "../ExtendedTutorials/NewtonsCradle.h" +#include "../ExtendedTutorials/MultiPendulum.h" struct ExampleEntry { @@ -269,11 +272,15 @@ static ExampleEntry gDefaultExamples[]= //Extended Tutorials Added by Mobeen ExampleEntry(0,"Extended Tutorials"), ExampleEntry(1,"Simple Box", "Simplest possible demo creating a single box rigid body that falls under gravity", ET_SimpleBoxCreateFunc), - ExampleEntry(1,"Multiple Boxes", "Adding multiple box rigid bodies that fall under gravity", ET_MultipleBoxesCreateFunc), - ExampleEntry(1,"Simple Joint", "Creating a single distance constraint between two box rigid bodies", ET_SimpleJointCreateFunc), - ExampleEntry(1,"Simple Cloth", "Creating a simple piece of cloth", ET_SimpleClothCreateFunc), - ExampleEntry(1,"Simple Chain", "Creating a simple chain using a pair of point2point/distance constraints. You may click and drag any box to see the chain respond.", ET_ChainCreateFunc), - ExampleEntry(1,"Simple Bridge", "Creating a simple bridge using a pair of point2point/distance constraints. You may click and drag any plank to see the bridge respond.", ET_BridgeCreateFunc), + ExampleEntry(1,"Multiple Boxes", "Add multiple box rigid bodies that fall under gravity", ET_MultipleBoxesCreateFunc), + ExampleEntry(1,"Simple Joint", "Create a single distance constraint between two box rigid bodies", ET_SimpleJointCreateFunc), + ExampleEntry(1,"Simple Cloth", "Create a simple piece of cloth", ET_SimpleClothCreateFunc), + ExampleEntry(1,"Simple Chain", "Create a simple chain using a pair of point2point/distance constraints. You may click and drag any box to see the chain respond.", ET_ChainCreateFunc), + ExampleEntry(1,"Simple Bridge", "Create a simple bridge using a pair of point2point/distance constraints. You may click and drag any plank to see the bridge respond.", ET_BridgeCreateFunc), + ExampleEntry(1,"Inclined Plane", "Create an inclined plane to show restitution and different types of friction. Use the sliders to vary restitution and friction and press space to reset the scene.", ET_InclinedPlaneCreateFunc), + ExampleEntry(1,"Newton's Cradle", "Create a Newton's Cradle using a pair of point2point/slider constraints. Press 1/2 to lengthen/shorten the pendula, press 3 to displace pendula. Use the sliders to select the number of pendula in total (reset simulation), the number of displaced pendula and other options.", ET_NewtonsCradleCreateFunc), + ExampleEntry(1,"Multi-Pendulum", "Create a Multi-Pendulum using point2point/slider constraints. Press 1/2 to lengthen/shorten the pendula, press 3 to displace pendula. Use the sliders to select the number of pendula in total (reset simulation), the number of displaced pendula and other options.",ET_MultiPendulumCreateFunc), + //todo: create a category/tutorial about advanced topics, such as optimizations, using different collision detection algorithm, different constraint solvers etc. //ExampleEntry(0,"Advanced"), diff --git a/examples/ExtendedTutorials/InclinedPlane.cpp b/examples/ExtendedTutorials/InclinedPlane.cpp new file mode 100644 index 000000000..dfe099094 --- /dev/null +++ b/examples/ExtendedTutorials/InclinedPlane.cpp @@ -0,0 +1,372 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2015 Google Inc. http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + + +#include "InclinedPlane.h" + +#include "btBulletDynamicsCommon.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "../CommonInterfaces/CommonRigidBodyBase.h" +#include "../CommonInterfaces/CommonParameterInterface.h" + +static btScalar gTilt = 20.0f/180.0f*SIMD_PI; // tilt the ramp 20 degrees + +static btScalar gRampFriction = 1; // set ramp friction to 1 + +static btScalar gRampRestitution = 0; // set ramp restitution to 0 (no restitution) + +static btScalar gBoxFriction = 1; // set box friction to 1 + +static btScalar gBoxRestitution = 0; // set box restitution to 0 + +static btScalar gSphereFriction = 1; // set sphere friction to 1 + +static btScalar gSphereRollingFriction = 1; // set sphere rolling friction to 1 + +static btScalar gSphereRestitution = 0; // set sphere restitution to 0 + +// handles for changes +static btRigidBody* ramp = NULL; +static btRigidBody* gBox = NULL; +static btRigidBody* gSphere = NULL; + +struct InclinedPlaneExample : public CommonRigidBodyBase +{ + InclinedPlaneExample(struct GUIHelperInterface* helper) + :CommonRigidBodyBase(helper) + { + } + virtual ~InclinedPlaneExample(){} + virtual void initPhysics(); + virtual void resetScene(); + virtual void renderScene(); + virtual void stepSimulation(float deltaTime); + virtual bool keyboardCallback(int key, int state); + void resetCamera() + { + float dist = 41; + float pitch = 52; + float yaw = 35; + float targetPos[3]={0,0.46,0}; + m_guiHelper->resetCamera(dist,pitch,yaw,targetPos[0],targetPos[1],targetPos[2]); + } + + + +}; + +void onBoxFrictionChanged(float friction); + +void onBoxRestitutionChanged(float restitution); + +void onSphereFrictionChanged(float friction); + +void onSphereRestitutionChanged(float restitution); + +void onRampInclinationChanged(float inclination); + +void onRampFrictionChanged(float friction); + +void onRampRestitutionChanged(float restitution); + +void InclinedPlaneExample::initPhysics() +{ + + { // create slider to change the ramp tilt + SliderParams slider("Ramp Tilt",&gTilt); + slider.m_minVal=0; + slider.m_maxVal=M_PI/2.0f; + slider.m_clampToNotches = false; + slider.m_callback = onRampInclinationChanged; + m_guiHelper->getParameterInterface()->registerSliderFloatParameter(slider); + } + + { // create slider to change the ramp friction + SliderParams slider("Ramp Friction",&gRampFriction); + slider.m_minVal=0; + slider.m_maxVal=10; + slider.m_clampToNotches = false; + slider.m_callback = onRampFrictionChanged; + m_guiHelper->getParameterInterface()->registerSliderFloatParameter(slider); + } + + { // create slider to change the ramp restitution + SliderParams slider("Ramp Restitution",&gRampRestitution); + slider.m_minVal=0; + slider.m_maxVal=1; + slider.m_clampToNotches = false; + slider.m_callback = onRampRestitutionChanged; + m_guiHelper->getParameterInterface()->registerSliderFloatParameter(slider); + } + + { // create slider to change the box friction + SliderParams slider("Box Friction",&gBoxFriction); + slider.m_minVal=0; + slider.m_maxVal=10; + slider.m_clampToNotches = false; + slider.m_callback = onBoxFrictionChanged; + m_guiHelper->getParameterInterface()->registerSliderFloatParameter(slider); + } + + { // create slider to change the box restitution + SliderParams slider("Box Restitution",&gBoxRestitution); + slider.m_minVal=0; + slider.m_maxVal=1; + slider.m_clampToNotches = false; + slider.m_callback = onBoxRestitutionChanged; + m_guiHelper->getParameterInterface()->registerSliderFloatParameter(slider); + } + + { // create slider to change the sphere friction + SliderParams slider("Sphere Friction",&gSphereFriction); + slider.m_minVal=0; + slider.m_maxVal=10; + slider.m_clampToNotches = false; + slider.m_callback = onSphereFrictionChanged; + m_guiHelper->getParameterInterface()->registerSliderFloatParameter(slider); + } + + { // create slider to change the sphere rolling friction + SliderParams slider("Sphere Rolling Friction",&gSphereRollingFriction); + slider.m_minVal=0; + slider.m_maxVal=10; + slider.m_clampToNotches = false; + slider.m_callback = onSphereRestitutionChanged; + m_guiHelper->getParameterInterface()->registerSliderFloatParameter(slider); + } + + { // create slider to change the sphere restitution + SliderParams slider("Sphere Restitution",&gSphereRestitution); + slider.m_minVal=0; + slider.m_maxVal=1; + slider.m_clampToNotches = false; + m_guiHelper->getParameterInterface()->registerSliderFloatParameter(slider); + } + + m_guiHelper->setUpAxis(1); // set Y axis as up axis + + createEmptyDynamicsWorld(); + + // create debug drawer + m_guiHelper->createPhysicsDebugDrawer(m_dynamicsWorld); + if (m_dynamicsWorld->getDebugDrawer()) + m_dynamicsWorld->getDebugDrawer()->setDebugMode(btIDebugDraw::DBG_DrawWireframe+btIDebugDraw::DBG_DrawContactPoints); + + + { // create a static ground + btBoxShape* groundShape = createBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(50.))); + m_collisionShapes.push_back(groundShape); + + btTransform groundTransform; + groundTransform.setIdentity(); + groundTransform.setOrigin(btVector3(0,-50,0)); + + btScalar mass(0.); + createRigidBody(mass,groundTransform,groundShape, btVector4(0,0,1,1)); + } + + { //create a static inclined plane + btBoxShape* inclinedPlaneShape = createBoxShape(btVector3(btScalar(20.),btScalar(1.),btScalar(10.))); + m_collisionShapes.push_back(inclinedPlaneShape); + + btTransform startTransform; + startTransform.setIdentity(); + + // position the inclined plane above ground + startTransform.setOrigin(btVector3( + btScalar(0), + btScalar(15), + btScalar(0))); + + btQuaternion incline; + incline.setRotation(btVector3(0,0,1),gTilt); + startTransform.setRotation(incline); + + btScalar mass(0.); + ramp = createRigidBody(mass,startTransform,inclinedPlaneShape); + ramp->setFriction(gRampFriction); + ramp->setRestitution(gRampRestitution); + } + + + { //create a cube above the inclined plane + btBoxShape* boxShape = createBoxShape(btVector3(1,1,1)); + + m_collisionShapes.push_back(boxShape); + + btTransform startTransform; + startTransform.setIdentity(); + + btScalar boxMass(1.f); + + startTransform.setOrigin( + btVector3(btScalar(0), btScalar(20), btScalar(2))); + + gBox = createRigidBody(boxMass, startTransform, boxShape); + gBox->forceActivationState(DISABLE_DEACTIVATION); // to prevent the box on the ramp from disabling + gBox->setFriction(gBoxFriction); + gBox->setRestitution(gBoxRestitution); + } + + { //create a sphere above the inclined plane + btSphereShape* sphereShape = new btSphereShape(btScalar(1)); + + m_collisionShapes.push_back(sphereShape); + + btTransform startTransform; + startTransform.setIdentity(); + + btScalar sphereMass(1.f); + + startTransform.setOrigin( + btVector3(btScalar(0), btScalar(20), btScalar(4))); + + gSphere = createRigidBody(sphereMass, startTransform, sphereShape); + gSphere->forceActivationState(DISABLE_DEACTIVATION); // to prevent the sphere on the ramp from disabling + gSphere->setFriction(gSphereFriction); + gSphere->setRestitution(gSphereRestitution); + gSphere->setRollingFriction(gSphereRollingFriction); + } + + m_guiHelper->autogenerateGraphicsObjects(m_dynamicsWorld); +} + +void InclinedPlaneExample::resetScene() { + { //reset a cube above the inclined plane + + btTransform startTransform; + startTransform.setIdentity(); + + startTransform.setOrigin( + btVector3(btScalar(0), btScalar(20), btScalar(2))); + + gBox->setWorldTransform(startTransform); + btVector3 zero(0, 0, 0); + gBox->setAngularVelocity(zero); + gBox->setLinearVelocity(zero); + gBox->clearForces(); + } + + { //reset a sphere above the inclined plane + btTransform startTransform; + startTransform.setIdentity(); + + startTransform.setOrigin( + btVector3(btScalar(0), btScalar(20), btScalar(4))); + + gSphere->setWorldTransform(startTransform); + btVector3 zero(0, 0, 0); + gSphere->setAngularVelocity(zero); + gSphere->setLinearVelocity(zero); + gSphere->clearForces(); + } +} + +void InclinedPlaneExample::stepSimulation(float deltaTime) +{ + if (m_dynamicsWorld) + { + m_dynamicsWorld->stepSimulation(deltaTime); + } + +} + + +void InclinedPlaneExample::renderScene() +{ + CommonRigidBodyBase::renderScene(); +} + +bool InclinedPlaneExample::keyboardCallback(int key, int state) { +// b3Printf("Key pressed: %d in state %d \n",key,state); + + switch (key) { + case 32 /*ASCII for space*/: { + resetScene(); + break; + } + } + + return false; +} + + +// GUI parameter modifiers +void onBoxFrictionChanged(float friction){ + if(gBox){ + gBox->setFriction(friction); +// b3Printf("Friction of box changed to %f",friction ); + } +} + +void onBoxRestitutionChanged(float restitution){ + if(gBox){ + gBox->setRestitution(restitution); + //b3Printf("Restitution of box changed to %f",restitution); + } +} + +void onSphereFrictionChanged(float friction){ + if(gSphere){ + gSphere->setFriction(friction); + //b3Printf("Friction of sphere changed to %f",friction ); + } +} + +void onSphereRestitutionChanged(float restitution){ + if(gSphere){ + gSphere->setRestitution(restitution); + //b3Printf("Restitution of sphere changed to %f",restitution); + } +} + +void onRampInclinationChanged(float inclination){ + if(ramp){ + btTransform startTransform; + startTransform.setIdentity(); + + // position the inclined plane above ground + startTransform.setOrigin( + btVector3(btScalar(0), btScalar(15), btScalar(0))); + + btQuaternion incline; + incline.setRotation(btVector3(0,0,1),gTilt); + startTransform.setRotation(incline); + ramp->setWorldTransform(startTransform); + //b3Printf("Inclination of ramp changed to %f",inclination ); + } +} + +void onRampFrictionChanged(float friction){ + if(ramp){ + ramp->setFriction(friction); + //b3Printf("Friction of ramp changed to %f \n",friction ); + } +} + +void onRampRestitutionChanged(float restitution){ + if(ramp){ + ramp->setRestitution(restitution); + //b3Printf("Restitution of ramp changed to %f \n",restitution); + } +} + + +CommonExampleInterface* ET_InclinedPlaneCreateFunc(CommonExampleOptions& options) +{ + return new InclinedPlaneExample(options.m_guiHelper); +} diff --git a/examples/ExtendedTutorials/InclinedPlane.h b/examples/ExtendedTutorials/InclinedPlane.h new file mode 100644 index 000000000..23ea92dfd --- /dev/null +++ b/examples/ExtendedTutorials/InclinedPlane.h @@ -0,0 +1,22 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2015 Google Inc. http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef ET_INCLINED_PLANE_EXAMPLE_H +#define ET_INCLINED_PLANE_EXAMPLE_H + +class CommonExampleInterface* ET_InclinedPlaneCreateFunc(struct CommonExampleOptions& options); + + +#endif //ET_INCLINED_PLANE_EXAMPLE_H diff --git a/examples/ExtendedTutorials/MultiPendulum.cpp b/examples/ExtendedTutorials/MultiPendulum.cpp new file mode 100644 index 000000000..8c4cff2e2 --- /dev/null +++ b/examples/ExtendedTutorials/MultiPendulum.cpp @@ -0,0 +1,418 @@ +/* + Bullet Continuous Collision Detection and Physics Library + Copyright (c) 2015 Google Inc. http://bulletphysics.org + + This software is provided 'as-is', without any express or implied warranty. + In no event will the authors be held liable for any damages arising from the use of this software. + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it freely, + subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + */ + +#include "MultiPendulum.h" + +#include // TODO: Should I use another data structure? +#include + +#include "btBulletDynamicsCommon.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "../CommonInterfaces/CommonRigidBodyBase.h" +#include "../CommonInterfaces/CommonParameterInterface.h" + +static btScalar gPendulaQty = 2; //TODO: This would actually be an Integer, but the Slider does not like integers, so I floor it when changed + +static btScalar gDisplacedPendula = 1; //TODO: This is an int as well + +static btScalar gPendulaRestitution = 1; // Default pendulum restitution is 1 to restore all force + +static btScalar gSphereRadius = 1; // The sphere radius + +static btScalar gCurrentPendulumLength = 8; + +static btScalar gInitialPendulumLength = 8; // Default pendulum length (distance between two spheres) + +static btScalar gDisplacementForce = 30; // The default force with which we move the pendulum + +struct MultiPendulumExample: public CommonRigidBodyBase { + MultiPendulumExample(struct GUIHelperInterface* helper) : + CommonRigidBodyBase(helper) { + } + + virtual ~MultiPendulumExample() { + } + + virtual void initPhysics(); // build a multi pendulum + + virtual void renderScene(); // render the scene to screen + + virtual void createMultiPendulum(btSphereShape* colShape, + btScalar pendulaQty, btScalar xPosition, btScalar yPosition,btScalar zPosition, + btScalar length, btScalar mass); // create a multi pendulum at the indicated x and y position, the specified number of pendula formed into a chain, each with indicated length and mass + + virtual void changePendulaLength(btScalar length); // change the pendulum length + + virtual void changePendulaRestitution(btScalar restitution); // change the pendula restitution + + virtual void stepSimulation(float deltaTime); // step the simulation + + virtual bool keyboardCallback(int key, int state); // handle keyboard callbacks + + void resetCamera() { + float dist = 41; + float pitch = 52; + float yaw = 35; + float targetPos[3] = { 0, 0.46, 0 }; + m_guiHelper->resetCamera(dist, pitch, yaw, targetPos[0], targetPos[1], + targetPos[2]); + } + + std::vector constraints; // keep a handle to the slider constraints + + std::vector pendula; // keep a handle to the pendula +}; + +static MultiPendulumExample* mex = NULL; // Handle to the example to access it via functions. Do not use this in your simulation! + +void onMultiPendulaLengthChanged(float pendulaLength); // Change the pendula length + +void onMultiPendulaRestitutionChanged(float pendulaRestitution); // change the pendula restitution + +void floorMSliderValue(float notUsed); // floor the slider values which should be integers + +void MultiPendulumExample::initPhysics() { // Setup your physics scene + + { // create a slider to change the number of pendula + SliderParams slider("Number of Pendula", &gPendulaQty); + slider.m_minVal = 1; + slider.m_maxVal = 50; + slider.m_callback = floorMSliderValue; // hack to get integer values + slider.m_clampToNotches = false; + m_guiHelper->getParameterInterface()->registerSliderFloatParameter( + slider); + } + + { // create a slider to change the number of displaced pendula + SliderParams slider("Number of Displaced Pendula", &gDisplacedPendula); + slider.m_minVal = 0; + slider.m_maxVal = 49; + slider.m_callback = floorMSliderValue; // hack to get integer values + slider.m_clampToNotches = false; + m_guiHelper->getParameterInterface()->registerSliderFloatParameter( + slider); + } + + { // create a slider to change the pendula restitution + SliderParams slider("Pendula Restitution", &gPendulaRestitution); + slider.m_minVal = 0; + slider.m_maxVal = 1; + slider.m_clampToNotches = false; + slider.m_callback = onMultiPendulaRestitutionChanged; + m_guiHelper->getParameterInterface()->registerSliderFloatParameter( + slider); + } + + { // create a slider to change the pendulum length + SliderParams slider("Pendula Length", &gCurrentPendulumLength); + slider.m_minVal = 0; + slider.m_maxVal = 49; + slider.m_clampToNotches = false; + slider.m_callback = onMultiPendulaLengthChanged; + m_guiHelper->getParameterInterface()->registerSliderFloatParameter( + slider); + } + + { // create a slider to change the force to displace the lowest pendulum + SliderParams slider("Displacement force", &gDisplacementForce); + slider.m_minVal = 0.1; + slider.m_maxVal = 200; + slider.m_clampToNotches = false; + m_guiHelper->getParameterInterface()->registerSliderFloatParameter( + slider); + } + + m_guiHelper->setUpAxis(1); + + createEmptyDynamicsWorld(); + + // create a debug drawer + m_guiHelper->createPhysicsDebugDrawer(m_dynamicsWorld); + if (m_dynamicsWorld->getDebugDrawer()) + m_dynamicsWorld->getDebugDrawer()->setDebugMode( + btIDebugDraw::DBG_DrawWireframe + + btIDebugDraw::DBG_DrawContactPoints + + btIDebugDraw::DBG_DrawConstraints + + btIDebugDraw::DBG_DrawConstraintLimits); + + { // create the multipendulum starting at the indicated position below and where each pendulum has the following mass + btScalar pendulumMass(1.f); + + btScalar xPosition(0.0f); // initial top-most pendulum position + btScalar yPosition(15.0f); + btScalar zPosition(0.0f); + + // Re-using the same collision is better for memory usage and performance + btSphereShape* pendulumShape = new btSphereShape(gSphereRadius); + m_collisionShapes.push_back(pendulumShape); + + // create multi-pendulum + createMultiPendulum(pendulumShape, floor(gPendulaQty), xPosition, yPosition,zPosition, + gInitialPendulumLength, pendulumMass); + } + + m_guiHelper->autogenerateGraphicsObjects(m_dynamicsWorld); +} + +void MultiPendulumExample::stepSimulation(float deltaTime) { + if (m_dynamicsWorld) { + m_dynamicsWorld->stepSimulation(deltaTime); + } + +} + +void MultiPendulumExample::createMultiPendulum(btSphereShape* colShape, + btScalar pendulaQty, btScalar xPosition, btScalar yPosition, btScalar zPosition, + btScalar length, btScalar mass) { + + // The multi-pendulum looks like this (names when built): + //..........0......./.......1...../.......2......./..etc...:pendulum build iterations + // O parentSphere + // | + // O childSphere / parentSphere + // | + // O ............./ childSphere / parentSphere + // | + // O .........................../ childSphere + // etc. + + //create the top element of the pendulum + btTransform startTransform; + startTransform.setIdentity(); + + // position the top sphere + startTransform.setOrigin( + btVector3(btScalar(xPosition), btScalar(yPosition), btScalar(zPosition))); + + startTransform.setRotation(btQuaternion(0, 0, 0, 1)); // zero rotation + + btRigidBody* topSphere = createRigidBody(mass, startTransform, colShape); + + // disable the deactivation when object does not move anymore + topSphere->setActivationState(DISABLE_DEACTIVATION); + + //make top sphere position "fixed" in the world by attaching it to a the world with a point to point constraint + // The pivot is defined in the reference frame of topSphere, so the attachment should be exactly at the center of topSphere + btVector3 constraintPivot(0.0f, 0.0f, 0.0f); + btPoint2PointConstraint* p2pconst = new btPoint2PointConstraint( + *topSphere, constraintPivot); + + p2pconst->setDbgDrawSize(btScalar(5.f)); // set the size of the debug drawing + + // add the constraint to the world + m_dynamicsWorld->addConstraint(p2pconst, true); + + btRigidBody* parentSphere = topSphere; // set the top sphere as the parent sphere for the next sphere to be created + + for (int i = 0; i < pendulaQty; i++) { // produce the number of pendula + + // create joint element to make the pendulum rotate it + + // position the joint sphere at the same position as the top sphere + startTransform.setOrigin( + btVector3(btScalar(xPosition), btScalar(yPosition - length*(i)), + btScalar(0))); + + startTransform.setRotation(btQuaternion(0, 0, 0, 1)); // zero rotation + + btRigidBody* jointSphere = createRigidBody(mass, startTransform, + colShape); + jointSphere->setFriction(0); // we do not need friction here + + // disable the deactivation when object does not move anymore + jointSphere->setActivationState(DISABLE_DEACTIVATION); + + //create constraint between parentSphere and jointSphere + // this is represented by the constraint pivot in the local frames of reference of both constrained spheres + btTransform constraintPivotInParentSphereRF, constraintPivotInJointSphereRF; + + constraintPivotInParentSphereRF.setIdentity(); + constraintPivotInJointSphereRF.setIdentity(); + + // the orientation of a point-to-point constraint does not matter, as is has no rotational limits + + //Obtain the position of parentSphere in local reference frame of the jointSphere (the pivot is therefore in the center of parentSphere) + btVector3 parentSphereInJointSphereRF = + (jointSphere->getWorldTransform().inverse()( + parentSphere->getWorldTransform().getOrigin())); + constraintPivotInJointSphereRF.setOrigin(parentSphereInJointSphereRF); + + btPoint2PointConstraint* p2pconst = new btPoint2PointConstraint( + *parentSphere,*jointSphere,constraintPivotInParentSphereRF.getOrigin(), constraintPivotInJointSphereRF.getOrigin()); + + p2pconst->setDbgDrawSize(btScalar(5.f)); // set the size of the debug drawing + + // add the constraint to the world + m_dynamicsWorld->addConstraint(p2pconst, true); + + // create a slider constraint to change the length of the pendula while it swings + + startTransform.setIdentity(); // reset start transform + + // position the child sphere below the joint sphere + startTransform.setOrigin( + btVector3(btScalar(xPosition), btScalar(yPosition - length*(i+1)), + btScalar(0))); + + startTransform.setRotation(btQuaternion(0, 0, 0, 1)); // zero rotation + + btRigidBody* childSphere = createRigidBody(mass, startTransform, + colShape); + childSphere->setFriction(0); // we do not need friction here + pendula.push_back(childSphere); + + // disable the deactivation when object does not move anymore + childSphere->setActivationState(DISABLE_DEACTIVATION); + + //create slider constraint between jointSphere and childSphere + // this is represented by the constraint pivot in the local frames of reference of both constrained spheres + // furthermore we need to rotate the constraint appropriately to orient it correctly in space + btTransform constraintPivotInChildSphereRF; + + constraintPivotInJointSphereRF.setIdentity(); + constraintPivotInChildSphereRF.setIdentity(); + + // the orientation of a point-to-point constraint does not matter, as is has no rotational limits + + //Obtain the position of jointSphere in local reference frame of the childSphere (the pivot is therefore in the center of jointSphere) + btVector3 jointSphereInChildSphereRF = + (childSphere->getWorldTransform().inverse()( + jointSphere->getWorldTransform().getOrigin())); + constraintPivotInChildSphereRF.setOrigin(jointSphereInChildSphereRF); + + // the slider constraint is x aligned per default, but we want it to be y aligned, therefore we rotate it + btQuaternion qt; + qt.setEuler(0, 0, -SIMD_HALF_PI); + constraintPivotInJointSphereRF.setRotation(qt); //we use Y like up Axis + constraintPivotInChildSphereRF.setRotation(qt); //we use Y like up Axis + + btSliderConstraint* sliderConst = new btSliderConstraint(*jointSphere, + *childSphere, constraintPivotInJointSphereRF, constraintPivotInChildSphereRF, true); + + sliderConst->setDbgDrawSize(btScalar(5.f)); // set the size of the debug drawing + + // set limits + // the initial setup of the constraint defines the origins of the limit dimensions, + // therefore we set both limits directly to the current position of the parentSphere + sliderConst->setLowerLinLimit(btScalar(0)); + sliderConst->setUpperLinLimit(btScalar(0)); + sliderConst->setLowerAngLimit(btScalar(0)); + sliderConst->setUpperAngLimit(btScalar(0)); + constraints.push_back(sliderConst); + + // add the constraint to the world + m_dynamicsWorld->addConstraint(sliderConst, true); + parentSphere = childSphere; + } +} + +void MultiPendulumExample::changePendulaLength(btScalar length) { + btScalar lowerLimit = -gInitialPendulumLength; + for (std::vector::iterator sit = constraints.begin(); + sit != constraints.end(); sit++) { + btAssert((*sit) && "Null constraint"); + + // if the pendulum is being shortened beyond it's own length, we don't let the lower sphere to go past the upper one + if (lowerLimit <= length) { + (*sit)->setLowerLinLimit(length + lowerLimit); + (*sit)->setUpperLinLimit(length + lowerLimit); + } + } +} + +void MultiPendulumExample::changePendulaRestitution(btScalar restitution) { + for (std::vector::iterator rit = pendula.begin(); + rit != pendula.end(); rit++) { + btAssert((*rit) && "Null constraint"); + + (*rit)->setRestitution(restitution); + } +} + +void MultiPendulumExample::renderScene() { + CommonRigidBodyBase::renderScene(); +} + +bool MultiPendulumExample::keyboardCallback(int key, int state) { + + //b3Printf("Key pressed: %d in state %d \n",key,state); + + //key 1, key 2, key 3 + switch (key) { + case 49 /*ASCII for 1*/: { + + //assumption: Sphere are aligned in Z axis + btScalar newLimit = gCurrentPendulumLength + 0.1; + + changePendulaLength(newLimit); + gCurrentPendulumLength = newLimit; + + b3Printf("Increase pendulum length to %f", gCurrentPendulumLength); + return true; + } + case 50 /*ASCII for 2*/: { + + //assumption: Sphere are aligned in Z axis + btScalar newLimit = gCurrentPendulumLength - 0.1; + + //is being shortened beyond it's own length, we don't let the lower sphere to go over the upper one + if (0 <= newLimit) { + changePendulaLength(newLimit); + gCurrentPendulumLength = newLimit; + } + + b3Printf("Decrease pendulum length to %f", gCurrentPendulumLength); + return true; + } + case 51 /*ASCII for 3*/: { + for (int i = gPendulaQty-1; i >= gPendulaQty-gDisplacedPendula; i--) { + if (gDisplacedPendula >= 0 && gDisplacedPendula < gPendulaQty) + pendula[i]->applyCentralForce(btVector3(gDisplacementForce, 0, 0)); + } + return true; + } + } + + return false; +} + +// GUI parameter modifiers + +void onMultiPendulaLengthChanged(float pendulaLength) { // Change the pendula length + if (mex){ + mex->changePendulaLength(pendulaLength); + } + //b3Printf("Pendula length changed to %f \n",sliderValue ); + +} + +void onMultiPendulaRestitutionChanged(float pendulaRestitution) { // change the pendula restitution + if (mex){ + mex->changePendulaRestitution(pendulaRestitution); + } + +} + +void floorMSliderValue(float notUsed) { // floor the slider values which should be integers + gPendulaQty = floor(gPendulaQty); + gDisplacedPendula = floor(gDisplacedPendula); +} + +CommonExampleInterface* ET_MultiPendulumCreateFunc( + CommonExampleOptions& options) { + mex = new MultiPendulumExample(options.m_guiHelper); + return mex; +} diff --git a/examples/ExtendedTutorials/MultiPendulum.h b/examples/ExtendedTutorials/MultiPendulum.h new file mode 100644 index 000000000..336c1be3c --- /dev/null +++ b/examples/ExtendedTutorials/MultiPendulum.h @@ -0,0 +1,22 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2015 Google Inc. http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef ET_MULTI_PENDULUM_EXAMPLE_H +#define ET_MULTI_PENDULUM_EXAMPLE_H + +class CommonExampleInterface* ET_MultiPendulumCreateFunc(struct CommonExampleOptions& options); + + +#endif //ET_MULTI_PENDULUM_EXAMPLE_H diff --git a/examples/ExtendedTutorials/NewtonsCradle.cpp b/examples/ExtendedTutorials/NewtonsCradle.cpp new file mode 100644 index 000000000..76bbf6622 --- /dev/null +++ b/examples/ExtendedTutorials/NewtonsCradle.cpp @@ -0,0 +1,350 @@ +/* + Bullet Continuous Collision Detection and Physics Library + Copyright (c) 2015 Google Inc. http://bulletphysics.org + + This software is provided 'as-is', without any express or implied warranty. + In no event will the authors be held liable for any damages arising from the use of this software. + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it freely, + subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + */ + +#include "NewtonsCradle.h" + +#include // TODO: Should I use another data structure? +#include + +#include "btBulletDynamicsCommon.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "../CommonInterfaces/CommonRigidBodyBase.h" +#include "../CommonInterfaces/CommonParameterInterface.h" + +static btScalar gPendulaQty = 5; // Number of pendula in newton's cradle +//TODO: This would actually be an Integer, but the Slider does not like integers, so I floor it when changed + +static btScalar gDisplacedPendula = 1; // number of displaced pendula +//TODO: This is an int as well + +static btScalar gPendulaRestitution = 1; // pendula restition when hitting against each other + +static btScalar gSphereRadius = 1; // pendula radius + +static btScalar gCurrentPendulumLength = 8; // current pendula length + +static btScalar gInitialPendulumLength = 8; // default pendula length + +static btScalar gForcingForce = 30; // default force to displace the pendula + +struct NewtonsCradleExample: public CommonRigidBodyBase { + NewtonsCradleExample(struct GUIHelperInterface* helper) : + CommonRigidBodyBase(helper) { + } + virtual ~NewtonsCradleExample() { + } + virtual void initPhysics(); + virtual void renderScene(); + virtual void createPendulum(btSphereShape* colShape, btScalar xPosition, + btScalar yPosition, btScalar zPosition, btScalar length, btScalar mass); + virtual void changePendulaLength(btScalar length); + virtual void changePendulaRestitution(btScalar restitution); + virtual void stepSimulation(float deltaTime); + virtual bool keyboardCallback(int key, int state); + void resetCamera() { + float dist = 41; + float pitch = 52; + float yaw = 35; + float targetPos[3] = { 0, 0.46, 0 }; + m_guiHelper->resetCamera(dist, pitch, yaw, targetPos[0], targetPos[1], + targetPos[2]); + } + + std::vector constraints; + std::vector pendula; +}; + +static NewtonsCradleExample* nex = NULL; + +void onPendulaLengthChanged(float pendulaLength); + +void onPendulaRestitutionChanged(float pendulaRestitution); + +void floorSliderValue(float notUsed); + +void NewtonsCradleExample::initPhysics() { + + { // create a slider to change the number of pendula + SliderParams slider("Number of Pendula", &gPendulaQty); + slider.m_minVal = 1; + slider.m_maxVal = 50; + slider.m_callback = floorSliderValue; // hack to get integer values + slider.m_clampToNotches = false; + m_guiHelper->getParameterInterface()->registerSliderFloatParameter( + slider); + } + + { // create a slider to change the number of displaced pendula + SliderParams slider("Number of Displaced Pendula", &gDisplacedPendula); + slider.m_minVal = 0; + slider.m_maxVal = 49; + slider.m_callback = floorSliderValue; // hack to get integer values + slider.m_clampToNotches = false; + m_guiHelper->getParameterInterface()->registerSliderFloatParameter( + slider); + } + + { // create a slider to change the pendula restitution + SliderParams slider("Pendula Restitution", &gPendulaRestitution); + slider.m_minVal = 0; + slider.m_maxVal = 1; + slider.m_clampToNotches = false; + slider.m_callback = onPendulaRestitutionChanged; + m_guiHelper->getParameterInterface()->registerSliderFloatParameter( + slider); + } + + { // create a slider to change the pendulum length + SliderParams slider("Pendula Length", &gCurrentPendulumLength); + slider.m_minVal = 0; + slider.m_maxVal = 49; + slider.m_clampToNotches = false; + slider.m_callback = onPendulaLengthChanged; + m_guiHelper->getParameterInterface()->registerSliderFloatParameter( + slider); + } + + { // create a slider to change the force to displace the lowest pendulum + SliderParams slider("Displacement force", &gForcingForce); + slider.m_minVal = 0.1; + slider.m_maxVal = 200; + slider.m_clampToNotches = false; + m_guiHelper->getParameterInterface()->registerSliderFloatParameter( + slider); + } + + m_guiHelper->setUpAxis(1); + + createEmptyDynamicsWorld(); + + // create a debug drawer + m_guiHelper->createPhysicsDebugDrawer(m_dynamicsWorld); + if (m_dynamicsWorld->getDebugDrawer()) + m_dynamicsWorld->getDebugDrawer()->setDebugMode( + btIDebugDraw::DBG_DrawWireframe + + btIDebugDraw::DBG_DrawContactPoints + + btIDebugDraw::DBG_DrawConstraints + + btIDebugDraw::DBG_DrawConstraintLimits); + + { // create the pendulum starting at the indicated position below and where each pendulum has the following mass + btScalar pendulumMass(1.f); + + btScalar xPosition(0.0f); // initial left-most pendulum position + btScalar yPosition(15.0f); + btScalar zPosition(0.0f); + + // Re-using the same collision is better for memory usage and performance + btSphereShape* pendulumShape = new btSphereShape(gSphereRadius); + m_collisionShapes.push_back(pendulumShape); + + for (int i = 0; i < floor(gPendulaQty); i++) { + + // create pendulum + createPendulum(pendulumShape, xPosition, yPosition,zPosition, + gInitialPendulumLength, pendulumMass); + + // displace the pendula 1.05 sphere size, so that they all nearly touch (small spacings in between + xPosition -= 2.1f * gSphereRadius; + } + } + + m_guiHelper->autogenerateGraphicsObjects(m_dynamicsWorld); +} + +void NewtonsCradleExample::stepSimulation(float deltaTime) { + if (m_dynamicsWorld) { + m_dynamicsWorld->stepSimulation(deltaTime); + } + +} + +void NewtonsCradleExample::createPendulum(btSphereShape* colShape, + btScalar xPosition, btScalar yPosition, btScalar zPosition, btScalar length, btScalar mass) { + + // The pendulum looks like this (names when built): + // O topSphere + // | + // O bottomSphere + + //create a dynamic pendulum + btTransform startTransform; + startTransform.setIdentity(); + + // position the top sphere above ground with a moving x position + startTransform.setOrigin( + btVector3(btScalar(xPosition), btScalar(yPosition), btScalar(zPosition))); + startTransform.setRotation(btQuaternion(0, 0, 0, 1)); // zero rotation + btRigidBody* topSphere = createRigidBody(mass, startTransform, colShape); + + // position the bottom sphere below the top sphere + startTransform.setOrigin( + btVector3(btScalar(xPosition), btScalar(yPosition - length), + btScalar(zPosition))); + + startTransform.setRotation(btQuaternion(0, 0, 0, 1)); // zero rotation + btRigidBody* bottomSphere = createRigidBody(mass, startTransform, colShape); + bottomSphere->setFriction(0); // we do not need friction here + pendula.push_back(bottomSphere); + + // disable the deactivation when objects do not move anymore + topSphere->setActivationState(DISABLE_DEACTIVATION); + bottomSphere->setActivationState(DISABLE_DEACTIVATION); + + bottomSphere->setRestitution(gPendulaRestitution); // set pendula restitution + + //make the top sphere position "fixed" to the world by attaching with a point to point constraint + // The pivot is defined in the reference frame of topSphere, so the attachment is exactly at the center of the topSphere + btVector3 constraintPivot(btVector3(0.0f, 0.0f, 0.0f)); + btPoint2PointConstraint* p2pconst = new btPoint2PointConstraint(*topSphere, + constraintPivot); + + p2pconst->setDbgDrawSize(btScalar(5.f)); // set the size of the debug drawing + + // add the constraint to the world + m_dynamicsWorld->addConstraint(p2pconst, true); + + //create constraint between spheres + // this is represented by the constraint pivot in the local frames of reference of both constrained spheres + // furthermore we need to rotate the constraint appropriately to orient it correctly in space + btTransform constraintPivotInTopSphereRF, constraintPivotInBottomSphereRF; + + constraintPivotInTopSphereRF.setIdentity(); + constraintPivotInBottomSphereRF.setIdentity(); + + // the slider constraint is x aligned per default, but we want it to be y aligned, therefore we rotate it + btQuaternion qt; + qt.setEuler(0, 0, -SIMD_HALF_PI); + constraintPivotInTopSphereRF.setRotation(qt); //we use Y like up Axis + constraintPivotInBottomSphereRF.setRotation(qt); //we use Y like up Axis + + //Obtain the position of topSphere in local reference frame of bottomSphere (the pivot is therefore in the center of topSphere) + btVector3 topSphereInBottomSphereRF = + (bottomSphere->getWorldTransform().inverse()( + topSphere->getWorldTransform().getOrigin())); + constraintPivotInBottomSphereRF.setOrigin(topSphereInBottomSphereRF); + + btSliderConstraint* sliderConst = new btSliderConstraint(*topSphere, + *bottomSphere, constraintPivotInTopSphereRF, constraintPivotInBottomSphereRF, true); + + sliderConst->setDbgDrawSize(btScalar(5.f)); // set the size of the debug drawing + + // set limits + // the initial setup of the constraint defines the origins of the limit dimensions, + // therefore we set both limits directly to the current position of the topSphere + sliderConst->setLowerLinLimit(btScalar(0)); + sliderConst->setUpperLinLimit(btScalar(0)); + sliderConst->setLowerAngLimit(btScalar(0)); + sliderConst->setUpperAngLimit(btScalar(0)); + constraints.push_back(sliderConst); + + // add the constraint to the world + m_dynamicsWorld->addConstraint(sliderConst, true); +} + +void NewtonsCradleExample::changePendulaLength(btScalar length) { + btScalar lowerLimit = -gInitialPendulumLength; + for (std::vector::iterator sit = constraints.begin(); + sit != constraints.end(); sit++) { + btAssert((*sit) && "Null constraint"); + + //if the pendulum is being shortened beyond it's own length, we don't let the lower sphere to go past the upper one + if (lowerLimit <= length) { + (*sit)->setLowerLinLimit(length + lowerLimit); + (*sit)->setUpperLinLimit(length + lowerLimit); + } + } +} + +void NewtonsCradleExample::changePendulaRestitution(btScalar restitution) { + for (std::vector::iterator rit = pendula.begin(); + rit != pendula.end(); rit++) { + btAssert((*rit) && "Null constraint"); + + (*rit)->setRestitution(restitution); + } +} + +void NewtonsCradleExample::renderScene() { + CommonRigidBodyBase::renderScene(); +} + +bool NewtonsCradleExample::keyboardCallback(int key, int state) { + //b3Printf("Key pressed: %d in state %d \n",key,state); + + //key 1, key 2, key 3 + switch (key) { + case 49 /*ASCII for 1*/: { + + //assumption: Sphere are aligned in Z axis + btScalar newLimit = gCurrentPendulumLength + 0.1; + + changePendulaLength(newLimit); + gCurrentPendulumLength = newLimit; + + b3Printf("Increase pendulum length to %f", gCurrentPendulumLength); + return true; + } + case 50 /*ASCII for 2*/: { + + //assumption: Sphere are aligned in Z axis + btScalar newLimit = gCurrentPendulumLength - 0.1; + + //is being shortened beyond it's own length, we don't let the lower sphere to go over the upper one + if (0 <= newLimit) { + changePendulaLength(newLimit); + gCurrentPendulumLength = newLimit; + } + + b3Printf("Decrease pendulum length to %f", gCurrentPendulumLength); + return true; + } + case 51 /*ASCII for 3*/: { + for (int i = 0; i < gDisplacedPendula; i++) { + if (gDisplacedPendula >= 0 && gDisplacedPendula <= gPendulaQty) + pendula[i]->applyCentralForce(btVector3(gForcingForce, 0, 0)); + } + return true; + } + } + + return false; +} + +// GUI parameter modifiers + +void onPendulaLengthChanged(float pendulaLength) { + if (nex){ + nex->changePendulaLength(pendulaLength); + //b3Printf("Pendula length changed to %f \n",sliderValue ); + } +} + +void onPendulaRestitutionChanged(float pendulaRestitution) { + if (nex){ + nex->changePendulaRestitution(pendulaRestitution); + } +} + +void floorSliderValue(float notUsed) { + gPendulaQty = floor(gPendulaQty); + gDisplacedPendula = floor(gDisplacedPendula); +} + +CommonExampleInterface* ET_NewtonsCradleCreateFunc( + CommonExampleOptions& options) { + nex = new NewtonsCradleExample(options.m_guiHelper); + return nex; +} diff --git a/examples/ExtendedTutorials/NewtonsCradle.h b/examples/ExtendedTutorials/NewtonsCradle.h new file mode 100644 index 000000000..9b9e2f247 --- /dev/null +++ b/examples/ExtendedTutorials/NewtonsCradle.h @@ -0,0 +1,22 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2015 Google Inc. http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef ET_NEWTONIAN_PENDULUM_EXAMPLE_H +#define ET_NEWTONIAN_PENDULUM_EXAMPLE_H + +class CommonExampleInterface* ET_NewtonsCradleCreateFunc(struct CommonExampleOptions& options); + + +#endif //ET_NEWTONIAN_PENDULUM_EXAMPLE_H From e46a718807d9d839d139d6c2c3f27662d5f7a810 Mon Sep 17 00:00:00 2001 From: Benjamin Ellenberger Date: Mon, 6 Jun 2016 23:47:33 +0200 Subject: [PATCH 03/14] Add btScalar fixes and correct M_PI to SIMD_PI. --- examples/ExtendedTutorials/InclinedPlane.cpp | 2 +- examples/ExtendedTutorials/MultiPendulum.cpp | 6 +++--- examples/ExtendedTutorials/NewtonsCradle.cpp | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/ExtendedTutorials/InclinedPlane.cpp b/examples/ExtendedTutorials/InclinedPlane.cpp index dfe099094..dceafdbe8 100644 --- a/examples/ExtendedTutorials/InclinedPlane.cpp +++ b/examples/ExtendedTutorials/InclinedPlane.cpp @@ -89,7 +89,7 @@ void InclinedPlaneExample::initPhysics() { // create slider to change the ramp tilt SliderParams slider("Ramp Tilt",&gTilt); slider.m_minVal=0; - slider.m_maxVal=M_PI/2.0f; + slider.m_maxVal=SIMD_PI/2.0f; slider.m_clampToNotches = false; slider.m_callback = onRampInclinationChanged; m_guiHelper->getParameterInterface()->registerSliderFloatParameter(slider); diff --git a/examples/ExtendedTutorials/MultiPendulum.cpp b/examples/ExtendedTutorials/MultiPendulum.cpp index 8c4cff2e2..0d29ce12d 100644 --- a/examples/ExtendedTutorials/MultiPendulum.cpp +++ b/examples/ExtendedTutorials/MultiPendulum.cpp @@ -355,7 +355,7 @@ bool MultiPendulumExample::keyboardCallback(int key, int state) { case 49 /*ASCII for 1*/: { //assumption: Sphere are aligned in Z axis - btScalar newLimit = gCurrentPendulumLength + 0.1; + btScalar newLimit = btScalar(gCurrentPendulumLength + 0.1); changePendulaLength(newLimit); gCurrentPendulumLength = newLimit; @@ -366,7 +366,7 @@ bool MultiPendulumExample::keyboardCallback(int key, int state) { case 50 /*ASCII for 2*/: { //assumption: Sphere are aligned in Z axis - btScalar newLimit = gCurrentPendulumLength - 0.1; + btScalar newLimit = btScalar(gCurrentPendulumLength - 0.1); //is being shortened beyond it's own length, we don't let the lower sphere to go over the upper one if (0 <= newLimit) { @@ -378,7 +378,7 @@ bool MultiPendulumExample::keyboardCallback(int key, int state) { return true; } case 51 /*ASCII for 3*/: { - for (int i = gPendulaQty-1; i >= gPendulaQty-gDisplacedPendula; i--) { + for (int i = floor(gPendulaQty)-1; i >= gPendulaQty-gDisplacedPendula; i--) { if (gDisplacedPendula >= 0 && gDisplacedPendula < gPendulaQty) pendula[i]->applyCentralForce(btVector3(gDisplacementForce, 0, 0)); } diff --git a/examples/ExtendedTutorials/NewtonsCradle.cpp b/examples/ExtendedTutorials/NewtonsCradle.cpp index 76bbf6622..a1c51f1fe 100644 --- a/examples/ExtendedTutorials/NewtonsCradle.cpp +++ b/examples/ExtendedTutorials/NewtonsCradle.cpp @@ -153,7 +153,7 @@ void NewtonsCradleExample::initPhysics() { for (int i = 0; i < floor(gPendulaQty); i++) { // create pendulum - createPendulum(pendulumShape, xPosition, yPosition,zPosition, + createPendulum(pendulumShape, xPosition, yPosition, zPosition, gInitialPendulumLength, pendulumMass); // displace the pendula 1.05 sphere size, so that they all nearly touch (small spacings in between @@ -289,7 +289,7 @@ bool NewtonsCradleExample::keyboardCallback(int key, int state) { case 49 /*ASCII for 1*/: { //assumption: Sphere are aligned in Z axis - btScalar newLimit = gCurrentPendulumLength + 0.1; + btScalar newLimit = btScalar(gCurrentPendulumLength + 0.1); changePendulaLength(newLimit); gCurrentPendulumLength = newLimit; @@ -300,7 +300,7 @@ bool NewtonsCradleExample::keyboardCallback(int key, int state) { case 50 /*ASCII for 2*/: { //assumption: Sphere are aligned in Z axis - btScalar newLimit = gCurrentPendulumLength - 0.1; + btScalar newLimit = btScalar(gCurrentPendulumLength - 0.1); //is being shortened beyond it's own length, we don't let the lower sphere to go over the upper one if (0 <= newLimit) { From e16082a7cd83de3bf28ac59434140d5789207f18 Mon Sep 17 00:00:00 2001 From: Benjamin Ellenberger Date: Mon, 27 Jun 2016 15:14:36 +0200 Subject: [PATCH 04/14] Refactor Newton's Cradle. Implement Newton's Cradle with Softbody ropes. --- examples/ExampleBrowser/CMakeLists.txt | 2 + examples/ExampleBrowser/ExampleEntries.cpp | 2 + examples/ExtendedTutorials/NewtonsCradle.cpp | 27 +- examples/ExtendedTutorials/NewtonsCradle.h | 6 +- .../ExtendedTutorials/NewtonsRopeCradle.cpp | 345 ++++++++++++++++++ .../ExtendedTutorials/NewtonsRopeCradle.h | 22 ++ 6 files changed, 385 insertions(+), 19 deletions(-) create mode 100644 examples/ExtendedTutorials/NewtonsRopeCradle.cpp create mode 100644 examples/ExtendedTutorials/NewtonsRopeCradle.h diff --git a/examples/ExampleBrowser/CMakeLists.txt b/examples/ExampleBrowser/CMakeLists.txt index 0af74fdb8..0546f1418 100644 --- a/examples/ExampleBrowser/CMakeLists.txt +++ b/examples/ExampleBrowser/CMakeLists.txt @@ -171,6 +171,8 @@ SET(BulletExampleBrowser_SRCS ../ExtendedTutorials/SimpleJoint.h ../ExtendedTutorials/NewtonsCradle.cpp ../ExtendedTutorials/NewtonsCradle.h + ../ExtendedTutorials/NewtonsRopeCradle.cpp + ../ExtendedTutorials/NewtonsRopeCradle.h ../ExtendedTutorials/InclinedPlane.cpp ../ExtendedTutorials/InclinedPlane.h ../ExtendedTutorials/MultiPendulum.cpp diff --git a/examples/ExampleBrowser/ExampleEntries.cpp b/examples/ExampleBrowser/ExampleEntries.cpp index 10cfe33ee..97bb1ad26 100644 --- a/examples/ExampleBrowser/ExampleEntries.cpp +++ b/examples/ExampleBrowser/ExampleEntries.cpp @@ -66,6 +66,7 @@ #include "../ExtendedTutorials/RigidBodyFromObj.h" #include "../ExtendedTutorials/InclinedPlane.h" #include "../ExtendedTutorials/NewtonsCradle.h" +#include "../ExtendedTutorials/NewtonsRopeCradle.h" #include "../ExtendedTutorials/MultiPendulum.h" struct ExampleEntry @@ -279,6 +280,7 @@ static ExampleEntry gDefaultExamples[]= ExampleEntry(1,"Simple Bridge", "Create a simple bridge using a pair of point2point/distance constraints. You may click and drag any plank to see the bridge respond.", ET_BridgeCreateFunc), ExampleEntry(1,"Inclined Plane", "Create an inclined plane to show restitution and different types of friction. Use the sliders to vary restitution and friction and press space to reset the scene.", ET_InclinedPlaneCreateFunc), ExampleEntry(1,"Newton's Cradle", "Create a Newton's Cradle using a pair of point2point/slider constraints. Press 1/2 to lengthen/shorten the pendula, press 3 to displace pendula. Use the sliders to select the number of pendula in total (reset simulation), the number of displaced pendula and other options.", ET_NewtonsCradleCreateFunc), + ExampleEntry(1,"Newton's Rope Cradle", "Create a Newton's Cradle using ropes. Press 3 to displace pendula. Use the sliders to select the number of pendula in total (reset simulation) and the number of displaced pendula.",ET_NewtonsRopeCradleCreateFunc), ExampleEntry(1,"Multi-Pendulum", "Create a Multi-Pendulum using point2point/slider constraints. Press 1/2 to lengthen/shorten the pendula, press 3 to displace pendula. Use the sliders to select the number of pendula in total (reset simulation), the number of displaced pendula and other options.",ET_MultiPendulumCreateFunc), diff --git a/examples/ExtendedTutorials/NewtonsCradle.cpp b/examples/ExtendedTutorials/NewtonsCradle.cpp index a1c51f1fe..a8b8d5773 100644 --- a/examples/ExtendedTutorials/NewtonsCradle.cpp +++ b/examples/ExtendedTutorials/NewtonsCradle.cpp @@ -30,7 +30,7 @@ static btScalar gPendulaQty = 5; // Number of pendula in newton's cradle static btScalar gDisplacedPendula = 1; // number of displaced pendula //TODO: This is an int as well -static btScalar gPendulaRestitution = 1; // pendula restition when hitting against each other +static btScalar gPendulaRestitution = 1; // pendula restitution when hitting against each other static btScalar gSphereRadius = 1; // pendula radius @@ -48,8 +48,7 @@ struct NewtonsCradleExample: public CommonRigidBodyBase { } virtual void initPhysics(); virtual void renderScene(); - virtual void createPendulum(btSphereShape* colShape, btScalar xPosition, - btScalar yPosition, btScalar zPosition, btScalar length, btScalar mass); + virtual void createPendulum(btSphereShape* colShape, btVector3 position, btScalar length, btScalar mass); virtual void changePendulaLength(btScalar length); virtual void changePendulaRestitution(btScalar restitution); virtual void stepSimulation(float deltaTime); @@ -139,12 +138,11 @@ void NewtonsCradleExample::initPhysics() { + btIDebugDraw::DBG_DrawConstraints + btIDebugDraw::DBG_DrawConstraintLimits); - { // create the pendulum starting at the indicated position below and where each pendulum has the following mass + { // create the pendula starting at the indicated position below and where each pendulum has the following mass btScalar pendulumMass(1.f); - btScalar xPosition(0.0f); // initial left-most pendulum position - btScalar yPosition(15.0f); - btScalar zPosition(0.0f); + btVector3 position(0.0f,15.0f,0.0f); // initial left-most pendulum position + btQuaternion orientation(0,0,0,1); // orientation of the pendula // Re-using the same collision is better for memory usage and performance btSphereShape* pendulumShape = new btSphereShape(gSphereRadius); @@ -153,11 +151,10 @@ void NewtonsCradleExample::initPhysics() { for (int i = 0; i < floor(gPendulaQty); i++) { // create pendulum - createPendulum(pendulumShape, xPosition, yPosition, zPosition, - gInitialPendulumLength, pendulumMass); + createPendulum(pendulumShape, position, gInitialPendulumLength, pendulumMass); // displace the pendula 1.05 sphere size, so that they all nearly touch (small spacings in between - xPosition -= 2.1f * gSphereRadius; + position.setX(position.x()-2.1f * gSphereRadius); } } @@ -171,8 +168,7 @@ void NewtonsCradleExample::stepSimulation(float deltaTime) { } -void NewtonsCradleExample::createPendulum(btSphereShape* colShape, - btScalar xPosition, btScalar yPosition, btScalar zPosition, btScalar length, btScalar mass) { +void NewtonsCradleExample::createPendulum(btSphereShape* colShape,btVector3 position, btScalar length, btScalar mass) { // The pendulum looks like this (names when built): // O topSphere @@ -184,15 +180,14 @@ void NewtonsCradleExample::createPendulum(btSphereShape* colShape, startTransform.setIdentity(); // position the top sphere above ground with a moving x position - startTransform.setOrigin( - btVector3(btScalar(xPosition), btScalar(yPosition), btScalar(zPosition))); + startTransform.setOrigin(position); startTransform.setRotation(btQuaternion(0, 0, 0, 1)); // zero rotation btRigidBody* topSphere = createRigidBody(mass, startTransform, colShape); // position the bottom sphere below the top sphere startTransform.setOrigin( - btVector3(btScalar(xPosition), btScalar(yPosition - length), - btScalar(zPosition))); + btVector3(position.x(), btScalar(position.y() - length), + position.z())); startTransform.setRotation(btQuaternion(0, 0, 0, 1)); // zero rotation btRigidBody* bottomSphere = createRigidBody(mass, startTransform, colShape); diff --git a/examples/ExtendedTutorials/NewtonsCradle.h b/examples/ExtendedTutorials/NewtonsCradle.h index 9b9e2f247..028754f7e 100644 --- a/examples/ExtendedTutorials/NewtonsCradle.h +++ b/examples/ExtendedTutorials/NewtonsCradle.h @@ -13,10 +13,10 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#ifndef ET_NEWTONIAN_PENDULUM_EXAMPLE_H -#define ET_NEWTONIAN_PENDULUM_EXAMPLE_H +#ifndef ET_NEWTONS_CRADLE_EXAMPLE_H +#define ET_NEWTONS_CRADLE_EXAMPLE_H class CommonExampleInterface* ET_NewtonsCradleCreateFunc(struct CommonExampleOptions& options); -#endif //ET_NEWTONIAN_PENDULUM_EXAMPLE_H +#endif //ET_NEWTONS_CRADLE_EXAMPLE_H diff --git a/examples/ExtendedTutorials/NewtonsRopeCradle.cpp b/examples/ExtendedTutorials/NewtonsRopeCradle.cpp new file mode 100644 index 000000000..d0a4b86a9 --- /dev/null +++ b/examples/ExtendedTutorials/NewtonsRopeCradle.cpp @@ -0,0 +1,345 @@ +/* + Bullet Continuous Collision Detection and Physics Library + Copyright (c) 2015 Google Inc. http://bulletphysics.org + + This software is provided 'as-is', without any express or implied warranty. + In no event will the authors be held liable for any damages arising from the use of this software. + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it freely, + subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + */ + +#include "NewtonsRopeCradle.h" + +#include // TODO: Should I use another data structure? +#include + +#include "btBulletDynamicsCommon.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "../CommonInterfaces/CommonRigidBodyBase.h" + +#include "BulletSoftBody/btSoftRigidDynamicsWorld.h" +#include "BulletSoftBody/btSoftBodyHelpers.h" +#include "BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h" +#include "../CommonInterfaces/CommonParameterInterface.h" + +static btScalar gPendulaQty = 5; // Number of pendula in newton's cradle +//TODO: This would actually be an Integer, but the Slider does not like integers, so I floor it when changed + +static btScalar gDisplacedPendula = 1; // number of displaced pendula +//TODO: This is an int as well + +static btScalar gPendulaRestitution = 1; // pendula restition when hitting against each other + +static btScalar gSphereRadius = 1; // pendula radius + +static btScalar gInitialPendulumWidth = 4; // default pendula width + +static btScalar gInitialPendulumHeight = 8; // default pendula height + +static btScalar gRopeResolution = 1; // default rope resolution (number of links as in a chain) + +static btScalar gForcingForce = 30; // default force to displace the pendula + +struct NewtonsRopeCradleExample : public CommonRigidBodyBase { + NewtonsRopeCradleExample(struct GUIHelperInterface* helper) : + CommonRigidBodyBase(helper) { + } + virtual ~NewtonsRopeCradleExample(){} + virtual void initPhysics(); + virtual void renderScene(); + void createEmptyDynamicsWorld() + { + m_collisionConfiguration = new btSoftBodyRigidBodyCollisionConfiguration(); + m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); + + m_broadphase = new btDbvtBroadphase(); + + m_solver = new btSequentialImpulseConstraintSolver; + + m_dynamicsWorld = new btSoftRigidDynamicsWorld(m_dispatcher, m_broadphase, m_solver, m_collisionConfiguration); + m_dynamicsWorld->setGravity(btVector3(0, -10, 0)); + + softBodyWorldInfo.m_broadphase = m_broadphase; + softBodyWorldInfo.m_dispatcher = m_dispatcher; + softBodyWorldInfo.m_gravity = m_dynamicsWorld->getGravity(); + softBodyWorldInfo.m_sparsesdf.Initialize(); + } + + virtual void createRopePendulum(btSphereShape* colShape, + btVector3 position, btQuaternion pendulumOrientation, btScalar width, btScalar height, btScalar mass); + virtual void changePendulaRestitution(btScalar restitution); + virtual void connectWithRope(btRigidBody* body1, btRigidBody* body2); + virtual bool keyboardCallback(int key, int state); + + virtual btSoftRigidDynamicsWorld* getSoftDynamicsWorld() + { + ///just make it a btSoftRigidDynamicsWorld please + ///or we will add type checking + return (btSoftRigidDynamicsWorld*) m_dynamicsWorld; + } + void resetCamera() + { + float dist = 41; + float pitch = 52; + float yaw = 35; + float targetPos[3]={0,0.46,0}; + m_guiHelper->resetCamera(dist,pitch,yaw,targetPos[0],targetPos[1],targetPos[2]); + } + + std::vector constraints; + std::vector pendula; + + btSoftBodyWorldInfo softBodyWorldInfo; + +}; + +static NewtonsRopeCradleExample* nex = NULL; + +void onRopePendulaRestitutionChanged(float pendulaRestitution); + +void floorRSliderValue(float notUsed); + +void NewtonsRopeCradleExample::initPhysics() +{ + + { // create a slider to change the number of pendula + SliderParams slider("Number of Pendula", &gPendulaQty); + slider.m_minVal = 1; + slider.m_maxVal = 50; + slider.m_callback = floorRSliderValue; // hack to get integer values + slider.m_clampToNotches = false; + m_guiHelper->getParameterInterface()->registerSliderFloatParameter( + slider); + } + + { // create a slider to change the number of displaced pendula + SliderParams slider("Number of Displaced Pendula", &gDisplacedPendula); + slider.m_minVal = 0; + slider.m_maxVal = 49; + slider.m_callback = floorRSliderValue; // hack to get integer values + slider.m_clampToNotches = false; + m_guiHelper->getParameterInterface()->registerSliderFloatParameter( + slider); + } + + { // create a slider to change the pendula restitution + SliderParams slider("Pendula Restitution", &gPendulaRestitution); + slider.m_minVal = 0; + slider.m_maxVal = 1; + slider.m_clampToNotches = false; + slider.m_callback = onRopePendulaRestitutionChanged; + m_guiHelper->getParameterInterface()->registerSliderFloatParameter( + slider); + } + + { // create a slider to change the rope resolution + SliderParams slider("Rope Resolution", &gRopeResolution); + slider.m_minVal = 1; + slider.m_maxVal = 20; + slider.m_clampToNotches = false; + slider.m_callback = floorRSliderValue; + m_guiHelper->getParameterInterface()->registerSliderFloatParameter( + slider); + } + + { // create a slider to change the pendulum width + SliderParams slider("Pendulum Width", &gInitialPendulumWidth); + slider.m_minVal = 0; + slider.m_maxVal = 40; + slider.m_clampToNotches = false; + m_guiHelper->getParameterInterface()->registerSliderFloatParameter( + slider); + } + + { // create a slider to change the pendulum height + SliderParams slider("Pendulum Height", &gInitialPendulumHeight); + slider.m_minVal = 0; + slider.m_maxVal = 40; + slider.m_clampToNotches = false; + m_guiHelper->getParameterInterface()->registerSliderFloatParameter( + slider); + } + + { // create a slider to change the force to displace the lowest pendulum + SliderParams slider("Displacement force", &gForcingForce); + slider.m_minVal = 0.1; + slider.m_maxVal = 200; + slider.m_clampToNotches = false; + m_guiHelper->getParameterInterface()->registerSliderFloatParameter( + slider); + } + + m_guiHelper->setUpAxis(1); + + createEmptyDynamicsWorld(); + + // create a debug drawer + m_guiHelper->createPhysicsDebugDrawer(m_dynamicsWorld); + if (m_dynamicsWorld->getDebugDrawer()) + m_dynamicsWorld->getDebugDrawer()->setDebugMode( + btIDebugDraw::DBG_DrawWireframe + + btIDebugDraw::DBG_DrawContactPoints + + btIDebugDraw::DBG_DrawConstraints + + btIDebugDraw::DBG_DrawConstraintLimits); + + { // create the pendula starting at the indicated position below and where each pendulum has the following mass + btScalar pendulumMass(1.0f); + + btVector3 position(0.0f,15.0f,0.0f); // initial left-most pendulum position + btQuaternion orientation(0,0,0,1); // orientation of the pendula + + // Re-using the same collision is better for memory usage and performance + btSphereShape* pendulumShape = new btSphereShape(gSphereRadius); + m_collisionShapes.push_back(pendulumShape); + + for (int i = 0; i < floor(gPendulaQty); i++) { + + // create pendulum + createRopePendulum(pendulumShape, position, orientation,gInitialPendulumWidth, + gInitialPendulumHeight, pendulumMass); + + // displace the pendula 1.05 sphere size, so that they all nearly touch (small spacings in between) + position.setX(position.x()-2.1f * gSphereRadius); + } + } + + m_guiHelper->autogenerateGraphicsObjects(m_dynamicsWorld); +} + +void NewtonsRopeCradleExample::connectWithRope(btRigidBody* body1, btRigidBody* body2) +{ + btSoftBody* softBodyRope0 = btSoftBodyHelpers::CreateRope(softBodyWorldInfo,body1->getWorldTransform().getOrigin(),body2->getWorldTransform().getOrigin(),gRopeResolution,0); + softBodyRope0->setTotalMass(0.1f); + + softBodyRope0->appendAnchor(0,body1); + softBodyRope0->appendAnchor(softBodyRope0->m_nodes.size()-1,body2); + + softBodyRope0->m_cfg.piterations = 5; + softBodyRope0->m_cfg.kDP = 0.005f; + softBodyRope0->m_cfg.kSHR = 1; + softBodyRope0->m_cfg.kCHR = 1; + softBodyRope0->m_cfg.kKHR = 1; + + getSoftDynamicsWorld()->addSoftBody(softBodyRope0); +} + +void NewtonsRopeCradleExample::createRopePendulum(btSphereShape* colShape, + btVector3 position, btQuaternion pendulumOrientation, btScalar width, btScalar height, btScalar mass) { + + // The pendulum looks like this (names when built): + // O O topSphere1 topSphere2 + // \ / + // O bottomSphere + + //create a dynamic pendulum + btTransform startTransform; + startTransform.setIdentity(); + + // calculate sphere positions + btVector3 topSphere1RelPosition(0,0,width); + btVector3 topSphere2RelPosition(0,0,-width); + btVector3 bottomSphereRelPosition(0,-height,0); + + + // position the top sphere above ground with appropriate orientation + startTransform.setOrigin(btVector3(0,0,0)); // no translation intitially + startTransform.setRotation(pendulumOrientation); // pendulum rotation + startTransform.setOrigin(startTransform * topSphere1RelPosition); // rotate this position + startTransform.setOrigin(position + startTransform.getOrigin()); // add non-rotated position to the relative position + btRigidBody* topSphere1 = createRigidBody(0, startTransform, colShape); // make top sphere static + + // position the top sphere above ground with appropriate orientation + startTransform.setOrigin(btVector3(0,0,0)); // no translation intitially + startTransform.setRotation(pendulumOrientation); // pendulum rotation + startTransform.setOrigin(startTransform * topSphere2RelPosition); // rotate this position + startTransform.setOrigin(position + startTransform.getOrigin()); // add non-rotated position to the relative position + btRigidBody* topSphere2 = createRigidBody(0, startTransform, colShape); // make top sphere static + + // position the bottom sphere below the top sphere + startTransform.setOrigin(btVector3(0,0,0)); // no translation intitially + startTransform.setRotation(pendulumOrientation); // pendulum rotation + startTransform.setOrigin(startTransform * bottomSphereRelPosition); // rotate this position + startTransform.setOrigin(position + startTransform.getOrigin()); // add non-rotated position to the relative position + btRigidBody* bottomSphere = createRigidBody(mass, startTransform, colShape); + bottomSphere->setFriction(0); // we do not need friction here + pendula.push_back(bottomSphere); + + // disable the deactivation when objects do not move anymore + topSphere1->setActivationState(DISABLE_DEACTIVATION); + topSphere2->setActivationState(DISABLE_DEACTIVATION); + bottomSphere->setActivationState(DISABLE_DEACTIVATION); + + bottomSphere->setRestitution(gPendulaRestitution); // set pendula restitution + + // add ropes between spheres + connectWithRope(topSphere1, bottomSphere); + connectWithRope(topSphere2, bottomSphere); +} + +void NewtonsRopeCradleExample::renderScene() +{ + CommonRigidBodyBase::renderScene(); + btSoftRigidDynamicsWorld* softWorld = getSoftDynamicsWorld(); + + for ( int i=0;igetSoftBodyArray().size();i++) + { + btSoftBody* psb=(btSoftBody*)softWorld->getSoftBodyArray()[i]; + //if (softWorld->getDebugDrawer() && !(softWorld->getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe))) + { + btSoftBodyHelpers::DrawFrame(psb,softWorld->getDebugDrawer()); + btSoftBodyHelpers::Draw(psb,softWorld->getDebugDrawer(),softWorld->getDrawFlags()); + } + } +} + +void NewtonsRopeCradleExample::changePendulaRestitution(btScalar restitution) { + for (std::vector::iterator rit = pendula.begin(); + rit != pendula.end(); rit++) { + btAssert((*rit) && "Null constraint"); + + (*rit)->setRestitution(restitution); + } +} + +bool NewtonsRopeCradleExample::keyboardCallback(int key, int state) { + //b3Printf("Key pressed: %d in state %d \n",key,state); + + // key 3 + switch (key) { + case 51 /*ASCII for 3*/: { + for (int i = 0; i < gDisplacedPendula; i++) { + if (gDisplacedPendula >= 0 && gDisplacedPendula <= gPendulaQty) + pendula[i]->applyCentralForce(btVector3(gForcingForce, 0, 0)); + } + return true; + } + } + + return false; +} + +// GUI parameter modifiers + +void onRopePendulaRestitutionChanged(float pendulaRestitution) { + if (nex){ + nex->changePendulaRestitution(pendulaRestitution); + } +} + +void floorRSliderValue(float notUsed) { + gPendulaQty = floor(gPendulaQty); + gDisplacedPendula = floor(gDisplacedPendula); + gRopeResolution = floor(gRopeResolution); +} + +CommonExampleInterface* ET_NewtonsRopeCradleCreateFunc( + CommonExampleOptions& options) { + nex = new NewtonsRopeCradleExample(options.m_guiHelper); + return nex; +} diff --git a/examples/ExtendedTutorials/NewtonsRopeCradle.h b/examples/ExtendedTutorials/NewtonsRopeCradle.h new file mode 100644 index 000000000..3edbcd5af --- /dev/null +++ b/examples/ExtendedTutorials/NewtonsRopeCradle.h @@ -0,0 +1,22 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2015 Google Inc. http://bulletphysics.org + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef ET_NEWTONS_ROPE_CRADLE_EXAMPLE_H +#define ET_NEWTONS_ROPE_CRADLE_EXAMPLE_H + +class CommonExampleInterface* ET_NewtonsRopeCradleCreateFunc(struct CommonExampleOptions& options); + + +#endif //ET_NEWTONS_ROPE_CRADLE_EXAMPLE_H From d0f20eafd161542ebf63c5f8061c5e266e3b8776 Mon Sep 17 00:00:00 2001 From: erwin coumans Date: Sat, 2 Jul 2016 18:53:19 -0700 Subject: [PATCH 05/14] Allow to build PhysicsServer in VR mode, to see the URDF/SDF robots in proper scale in VR. Add option to have Z as up-axis for VR examples. Add OpenVR LICENSE + README file Don't crash VR app when no HMD is detected, just exit. For now, don't request debug lines in client, it slows down physics server in VR mode too much. --- build_visual_studio.bat | 2 +- .../SharedMemory/PhysicsClientExample.cpp | 3 +- .../SharedMemory/PhysicsServerExample.cpp | 2 + examples/SharedMemory/premake4.lua | 62 ++++++++++++++++++- .../StandaloneMain/hellovr_opengl_main.cpp | 40 ++++++++---- examples/ThirdPartyLibs/openvr/LICENSE | 27 ++++++++ examples/ThirdPartyLibs/openvr/README | 9 +++ 7 files changed, 129 insertions(+), 16 deletions(-) create mode 100644 examples/ThirdPartyLibs/openvr/LICENSE create mode 100644 examples/ThirdPartyLibs/openvr/README diff --git a/build_visual_studio.bat b/build_visual_studio.bat index de3b886c9..56ee9f610 100644 --- a/build_visual_studio.bat +++ b/build_visual_studio.bat @@ -2,7 +2,7 @@ rem premake4 --with-pe vs2010 rem premake4 --bullet2demos vs2010 cd build3 -premake4 --targetdir="../bin" vs2010 +premake4 --enable_openvr --targetdir="../bin" vs2010 rem premake4 --targetdir="../server2bin" vs2010 rem cd vs2010 rem rename 0_Bullet3Solution.sln 0_server.sln diff --git a/examples/SharedMemory/PhysicsClientExample.cpp b/examples/SharedMemory/PhysicsClientExample.cpp index a4199071a..e8e181992 100644 --- a/examples/SharedMemory/PhysicsClientExample.cpp +++ b/examples/SharedMemory/PhysicsClientExample.cpp @@ -835,7 +835,7 @@ void PhysicsClientExample::stepSimulation(float deltaTime) enqueueCommand(CMD_STEP_FORWARD_SIMULATION); if (m_options != eCLIENTEXAMPLE_SERVER) { - enqueueCommand(CMD_REQUEST_DEBUG_LINES); + //enqueueCommand(CMD_REQUEST_DEBUG_LINES); } } } @@ -855,3 +855,4 @@ class CommonExampleInterface* PhysicsClientCreateFunc(struct CommonExampleOpt } return example; } + diff --git a/examples/SharedMemory/PhysicsServerExample.cpp b/examples/SharedMemory/PhysicsServerExample.cpp index 05c689e8a..7cb76e9c6 100644 --- a/examples/SharedMemory/PhysicsServerExample.cpp +++ b/examples/SharedMemory/PhysicsServerExample.cpp @@ -306,3 +306,5 @@ class CommonExampleInterface* PhysicsServerCreateFunc(struct CommonExampleOpt return example; } + +B3_STANDALONE_EXAMPLE(PhysicsServerCreateFunc) \ No newline at end of file diff --git a/examples/SharedMemory/premake4.lua b/examples/SharedMemory/premake4.lua index 34aea2de5..be3c7102c 100644 --- a/examples/SharedMemory/premake4.lua +++ b/examples/SharedMemory/premake4.lua @@ -15,7 +15,8 @@ links { language "C++" -files { +myfiles = +{ "PhysicsClient.cpp", "PhysicsClientSharedMemory.cpp", "PhysicsClientExample.cpp", @@ -24,7 +25,6 @@ files { "PhysicsServerSharedMemory.h", "PhysicsServer.cpp", "PhysicsServer.h", - "main.cpp", "PhysicsClientC_API.cpp", "SharedMemoryCommands.h", "SharedMemoryPublic.h", @@ -84,3 +84,61 @@ files { "../ThirdPartyLibs/stb_image/stb_image.cpp", } +files { + myfiles, + "main.cpp", +} + + + +project "App_SharedMemoryPhysics_VR" + +defines {"B3_USE_STANDALONE_EXAMPLE","BT_ENABLE_VR"} + +if _OPTIONS["ios"] then + kind "WindowedApp" +else + kind "ConsoleApp" +end + +includedirs { + ".","../../src", "../ThirdPartyLibs", + "../ThirdPartyLibs/openvr/headers", + "../ThirdPartyLibs/openvr/samples/shared" + } + +links { + "Bullet3Common", "BulletDynamics","BulletCollision", "LinearMath","OpenGL_Window","openvr_api" +} + +language "C++" + + + initOpenGL() + initGlew() + + +files +{ + myfiles, + "../StandaloneMain/hellovr_opengl_main.cpp", + "../ExampleBrowser/OpenGLGuiHelper.cpp", + "../ExampleBrowser/GL_ShapeDrawer.cpp", + "../ExampleBrowser/CollisionShape2TriangleMesh.cpp", + "../ThirdPartyLibs/openvr/samples/shared/lodepng.cpp", + "../ThirdPartyLibs/openvr/samples/shared/lodepng.h", + "../ThirdPartyLibs/openvr/samples/shared/Matrices.cpp", + "../ThirdPartyLibs/openvr/samples/shared/Matrices.h", + "../ThirdPartyLibs/openvr/samples/shared/pathtools.cpp", + "../ThirdPartyLibs/openvr/samples/shared/pathtools.h", + "../ThirdPartyLibs/openvr/samples/shared/Vectors.h", +} +if os.is("Windows") then + libdirs {"../ThirdPartyLibs/openvr/lib/win32"} +end + +if os.is("Linux") then initX11() end + +if os.is("MacOSX") then + links{"Cocoa.framework"} +end \ No newline at end of file diff --git a/examples/StandaloneMain/hellovr_opengl_main.cpp b/examples/StandaloneMain/hellovr_opengl_main.cpp index 746f10835..547f813fd 100644 --- a/examples/StandaloneMain/hellovr_opengl_main.cpp +++ b/examples/StandaloneMain/hellovr_opengl_main.cpp @@ -11,6 +11,7 @@ #include "BulletCollision/CollisionShapes/btCollisionShape.h" #include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h" +int gSharedMemoryKey = -1; //how can you try typing on a keyboard, without seeing it? //it is pretty funny, to see the desktop in VR! @@ -139,7 +140,7 @@ private: SimpleOpenGL3App* m_app; uint32_t m_nWindowWidth; uint32_t m_nWindowHeight; - + bool m_hasContext; private: // OpenGL bookkeeping int m_iTrackedControllerCount; @@ -234,6 +235,7 @@ private: // OpenGL bookkeeping //----------------------------------------------------------------------------- CMainApplication::CMainApplication( int argc, char *argv[] ) : m_app(NULL) + , m_hasContext(false) , m_nWindowWidth( 1280 ) , m_nWindowHeight( 720 ) , m_unSceneProgramID( 0 ) @@ -556,13 +558,16 @@ void CMainApplication::Shutdown() } m_vecRenderModels.clear(); - if( 1)//m_pContext ) + if( m_hasContext) { - glDebugMessageControl( GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_FALSE ); - glDebugMessageCallback(nullptr, nullptr); - glDeleteBuffers(1, &m_glSceneVertBuffer); - glDeleteBuffers(1, &m_glIDVertBuffer); - glDeleteBuffers(1, &m_glIDIndexBuffer); + if (m_glSceneVertBuffer) + { + glDebugMessageControl( GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_FALSE ); + glDebugMessageCallback(nullptr, nullptr); + glDeleteBuffers(1, &m_glSceneVertBuffer); + glDeleteBuffers(1, &m_glIDVertBuffer); + glDeleteBuffers(1, &m_glIDIndexBuffer); + } if ( m_unSceneProgramID ) { @@ -1067,6 +1072,7 @@ void CMainApplication::SetupScene() glDisableVertexAttribArray(0); glDisableVertexAttribArray(1); + m_hasContext = true; } @@ -1462,10 +1468,19 @@ void CMainApplication::RenderStereoTargets() m_app->m_instancingRenderer->init(); + Matrix4 rotYtoZ = rotYtoZ.identity(); + + //some Bullet apps (especially robotics related) require Z as up-axis) + if (m_app->getUpAxis()==2) + { + rotYtoZ.rotateX(-90); + } // Left Eye { - Matrix4 viewMatLeft = m_mat4eyePosLeft * m_mat4HMDPose; + + Matrix4 viewMatLeft = m_mat4eyePosLeft * m_mat4HMDPose * rotYtoZ; + m_app->m_instancingRenderer->getActiveCamera()->setVRCamera(viewMatLeft.get(),m_mat4ProjectionLeft.get()); m_app->m_instancingRenderer->updateCamera(); } @@ -1477,8 +1492,9 @@ void CMainApplication::RenderStereoTargets() m_app->m_window->startRendering(); RenderScene( vr::Eye_Left ); - - m_app->drawGrid(); + DrawGridData gridUp; + gridUp.upAxis = m_app->getUpAxis(); + m_app->drawGrid(gridUp); sExample->stepSimulation(1./60.); sExample->renderScene(); @@ -1507,7 +1523,7 @@ void CMainApplication::RenderStereoTargets() // Right Eye { - Matrix4 viewMatRight = m_mat4eyePosRight * m_mat4HMDPose; + Matrix4 viewMatRight = m_mat4eyePosRight * m_mat4HMDPose * rotYtoZ; m_app->m_instancingRenderer->getActiveCamera()->setVRCamera(viewMatRight.get(),m_mat4ProjectionRight.get()); m_app->m_instancingRenderer->updateCamera(); } @@ -1518,7 +1534,7 @@ void CMainApplication::RenderStereoTargets() m_app->m_window->startRendering(); RenderScene( vr::Eye_Right ); - m_app->drawGrid(); + m_app->drawGrid(gridUp); m_app->m_instancingRenderer->setRenderFrameBuffer((unsigned int)rightEyeDesc.m_nRenderFramebufferId); m_app->m_renderer->renderScene(); diff --git a/examples/ThirdPartyLibs/openvr/LICENSE b/examples/ThirdPartyLibs/openvr/LICENSE new file mode 100644 index 000000000..ee83337d7 --- /dev/null +++ b/examples/ThirdPartyLibs/openvr/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2015, Valve Corporation +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/examples/ThirdPartyLibs/openvr/README b/examples/ThirdPartyLibs/openvr/README new file mode 100644 index 000000000..9a8923159 --- /dev/null +++ b/examples/ThirdPartyLibs/openvr/README @@ -0,0 +1,9 @@ +OpenVR is an API and runtime that allows access to VR hardware from multiple +vendors without requiring that applications have specific knowledge of the +hardware they are targeting. This repository is an SDK that contains the API +and samples. The runtime is under SteamVR in Tools on Steam. + +Documentation for the API is available in the wiki: https://github.com/ValveSoftware/openvr/wiki/API-Documentation + +More information on OpenVR and SteamVR can be found on http://steamvr.com + From 60d2b99151650f441f80928d19f01a1e20ae2dc8 Mon Sep 17 00:00:00 2001 From: erwin coumans Date: Thu, 7 Jul 2016 19:24:44 -0700 Subject: [PATCH 06/14] Physics runs in a separate thread from rendering in PhysicsServerExample (preliminary) Improve rendering performance. OpenVR experience is smooth now. commit needs a bit more testing before pushing in main repo. --- data/sphere2.urdf | 52 +- .../CommonGUIHelperInterface.h | 12 +- .../CommonInterfaces/CommonRenderInterface.h | 2 + examples/ExampleBrowser/OpenGLGuiHelper.cpp | 17 +- examples/ExampleBrowser/OpenGLGuiHelper.h | 7 +- .../ExtendedTutorials/RigidBodyFromObj.cpp | 3 +- .../ImportURDFDemo/BulletUrdfImporter.cpp | 14 +- .../ImportURDFDemo/ImportURDFSetup.cpp | 18 +- .../ImportURDFDemo/MyMultiBodyCreator.cpp | 7 +- .../ImportURDFDemo/MyMultiBodyCreator.h | 5 + .../MultiThreading/b3PosixThreadSupport.cpp | 2 +- .../MultiThreading/b3Win32ThreadSupport.cpp | 4 +- .../OpenGLWindow/GLInstancingRenderer.cpp | 60 +- examples/OpenGLWindow/GLInstancingRenderer.h | 2 + .../OpenGLWindow/SimpleOpenGL2Renderer.cpp | 6 + examples/OpenGLWindow/SimpleOpenGL2Renderer.h | 3 + .../PhysicsClientSharedMemory.cpp | 2 + .../PhysicsServerCommandProcessor.cpp | 22 +- .../SharedMemory/PhysicsServerExample.cpp | 574 +++++++++++++++++- .../PhysicsServerSharedMemory.cpp | 5 + .../SharedMemory/PhysicsServerSharedMemory.h | 1 + examples/SharedMemory/premake4.lua | 214 +++++-- .../StandaloneMain/hellovr_opengl_main.cpp | 44 +- .../main_opengl_single_example.cpp | 21 +- .../main_sw_tinyrenderer_single_example.cpp | 14 +- .../main_tinyrenderer_single_example.cpp | 37 +- examples/pybullet/pybullet.c | 16 +- test/SharedMemory/test.c | 2 +- 28 files changed, 978 insertions(+), 188 deletions(-) diff --git a/data/sphere2.urdf b/data/sphere2.urdf index fb0108b3d..ec939e694 100644 --- a/data/sphere2.urdf +++ b/data/sphere2.urdf @@ -9,7 +9,7 @@ - + @@ -19,55 +19,5 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/CommonInterfaces/CommonGUIHelperInterface.h b/examples/CommonInterfaces/CommonGUIHelperInterface.h index b9a4dfd26..f76414126 100644 --- a/examples/CommonInterfaces/CommonGUIHelperInterface.h +++ b/examples/CommonInterfaces/CommonGUIHelperInterface.h @@ -29,9 +29,10 @@ struct GUIHelperInterface virtual void createPhysicsDebugDrawer( btDiscreteDynamicsWorld* rbWorld)=0; - virtual int registerGraphicsShape(const float* vertices, int numvertices, const int* indices, int numIndices) =0; - + virtual int registerTexture(const unsigned char* texels, int width, int height)=0; + virtual int registerGraphicsShape(const float* vertices, int numvertices, const int* indices, int numIndices,int primitiveType, int textureId) = 0; virtual int registerGraphicsInstance(int shapeIndex, const float* position, const float* quaternion, const float* color, const float* scaling) =0; + virtual void removeAllGraphicsInstances()=0; virtual Common2dCanvasInterface* get2dCanvasInterface()=0; @@ -73,9 +74,10 @@ struct DummyGUIHelper : public GUIHelperInterface virtual void createPhysicsDebugDrawer( btDiscreteDynamicsWorld* rbWorld){} - virtual int registerGraphicsShape(const float* vertices, int numvertices, const int* indices, int numIndices) { return -1; } - - virtual int registerGraphicsInstance(int shapeIndex, const float* position, const float* quaternion, const float* color, const float* scaling) { return -1;} + virtual int registerTexture(const unsigned char* texels, int width, int height){return -1;} + virtual int registerGraphicsShape(const float* vertices, int numvertices, const int* indices, int numIndices,int primitiveType, int textureId){return -1;} + virtual int registerGraphicsInstance(int shapeIndex, const float* position, const float* quaternion, const float* color, const float* scaling) {return -1;} + virtual void removeAllGraphicsInstances(){} virtual Common2dCanvasInterface* get2dCanvasInterface() { diff --git a/examples/CommonInterfaces/CommonRenderInterface.h b/examples/CommonInterfaces/CommonRenderInterface.h index e1d6170ef..0242a2bbe 100644 --- a/examples/CommonInterfaces/CommonRenderInterface.h +++ b/examples/CommonInterfaces/CommonRenderInterface.h @@ -53,6 +53,8 @@ struct CommonRenderInterface virtual void writeSingleInstanceColorToCPU(float* color, int srcIndex)=0; virtual void writeSingleInstanceColorToCPU(double* color, int srcIndex)=0; + virtual int getTotalNumInstances() const = 0; + virtual void writeTransforms()=0; virtual void enableBlend(bool blend)=0; virtual void clearZBuffer()=0; diff --git a/examples/ExampleBrowser/OpenGLGuiHelper.cpp b/examples/ExampleBrowser/OpenGLGuiHelper.cpp index 23c225677..0af5c8577 100644 --- a/examples/ExampleBrowser/OpenGLGuiHelper.cpp +++ b/examples/ExampleBrowser/OpenGLGuiHelper.cpp @@ -199,9 +199,16 @@ void OpenGLGuiHelper::createCollisionObjectGraphicsObject(btCollisionObject* bod } } -int OpenGLGuiHelper::registerGraphicsShape(const float* vertices, int numvertices, const int* indices, int numIndices) +int OpenGLGuiHelper::registerTexture(const unsigned char* texels, int width, int height) { - int shapeId = m_data->m_glApp->m_renderer->registerShape(vertices, numvertices,indices,numIndices); + int textureId = m_data->m_glApp->m_renderer->registerTexture(texels,width,height); + return textureId; +} + + +int OpenGLGuiHelper::registerGraphicsShape(const float* vertices, int numvertices, const int* indices, int numIndices,int primitiveType, int textureId) +{ + int shapeId = m_data->m_glApp->m_renderer->registerShape(vertices, numvertices,indices,numIndices,primitiveType, textureId); return shapeId; } @@ -210,6 +217,10 @@ int OpenGLGuiHelper::registerGraphicsInstance(int shapeIndex, const float* posit return m_data->m_glApp->m_renderer->registerGraphicsInstance(shapeIndex,position,quaternion,color,scaling); } +void OpenGLGuiHelper::removeAllGraphicsInstances() +{ + m_data->m_glApp->m_renderer->removeAllInstances(); +} void OpenGLGuiHelper::createCollisionShapeGraphicsObject(btCollisionShape* collisionShape) { @@ -247,7 +258,7 @@ void OpenGLGuiHelper::createCollisionShapeGraphicsObject(btCollisionShape* colli if (gfxVertices.size() && indices.size()) { - int shapeId = registerGraphicsShape(&gfxVertices[0].xyzw[0],gfxVertices.size(),&indices[0],indices.size()); + int shapeId = registerGraphicsShape(&gfxVertices[0].xyzw[0],gfxVertices.size(),&indices[0],indices.size(),B3_GL_TRIANGLES,-1); collisionShape->setUserIndex(shapeId); } diff --git a/examples/ExampleBrowser/OpenGLGuiHelper.h b/examples/ExampleBrowser/OpenGLGuiHelper.h index 0184d6ea0..72d784a0c 100644 --- a/examples/ExampleBrowser/OpenGLGuiHelper.h +++ b/examples/ExampleBrowser/OpenGLGuiHelper.h @@ -20,11 +20,10 @@ struct OpenGLGuiHelper : public GUIHelperInterface virtual void createCollisionObjectGraphicsObject(btCollisionObject* body, const btVector3& color); - virtual int registerGraphicsShape(const float* vertices, int numvertices, const int* indices, int numIndices); - + virtual int registerTexture(const unsigned char* texels, int width, int height); + virtual int registerGraphicsShape(const float* vertices, int numvertices, const int* indices, int numIndices,int primitiveType, int textureId); virtual int registerGraphicsInstance(int shapeIndex, const float* position, const float* quaternion, const float* color, const float* scaling); - - + virtual void removeAllGraphicsInstances(); virtual void createCollisionShapeGraphicsObject(btCollisionShape* collisionShape); diff --git a/examples/ExtendedTutorials/RigidBodyFromObj.cpp b/examples/ExtendedTutorials/RigidBodyFromObj.cpp index 64d52793d..9e09f9dd9 100644 --- a/examples/ExtendedTutorials/RigidBodyFromObj.cpp +++ b/examples/ExtendedTutorials/RigidBodyFromObj.cpp @@ -134,7 +134,8 @@ void RigidBodyFromObjExample::initPhysics() int shapeId = m_guiHelper->registerGraphicsShape(&glmesh->m_vertices->at(0).xyzw[0], glmesh->m_numvertices, &glmesh->m_indices->at(0), - glmesh->m_numIndices); + glmesh->m_numIndices, + B3_GL_TRIANGLES, -1); shape->setUserIndex(shapeId); int renderInstance = m_guiHelper->registerGraphicsInstance(shapeId,pos,orn,color,scaling); body->setUserIndex(renderInstance); diff --git a/examples/Importers/ImportURDFDemo/BulletUrdfImporter.cpp b/examples/Importers/ImportURDFDemo/BulletUrdfImporter.cpp index 9b6eb8ae1..555acf530 100644 --- a/examples/Importers/ImportURDFDemo/BulletUrdfImporter.cpp +++ b/examples/Importers/ImportURDFDemo/BulletUrdfImporter.cpp @@ -108,7 +108,8 @@ struct BulletErrorLogger : public ErrorLogger bool BulletURDFImporter::loadURDF(const char* fileName, bool forceFixedBase) { - + if (strlen(fileName)==0) + return false; //int argc=0; char relativeFileName[1024]; @@ -132,7 +133,7 @@ bool BulletURDFImporter::loadURDF(const char* fileName, bool forceFixedBase) std::fstream xml_file(relativeFileName, std::fstream::in); - while ( xml_file.good() ) + while ( xml_file.good()) { std::string line; std::getline( xml_file, line); @@ -969,16 +970,17 @@ int BulletURDFImporter::convertLinkVisualShapes(int linkIndex, const char* pathP // graphicsIndex = m_data->m_guiHelper->registerGraphicsShape(&vertices[0].xyzw[0], vertices.size(), &indices[0], indices.size()); //graphicsIndex = m_data->m_guiHelper->registerGraphicsShape(&vertices[0].xyzw[0], vertices.size(), &indices[0], indices.size()); - CommonRenderInterface* renderer = m_data->m_guiHelper->getRenderInterface(); + //CommonRenderInterface* renderer = m_data->m_guiHelper->getRenderInterface(); - if (renderer) + if (1) { int textureIndex = -1; if (textures.size()) { - textureIndex = renderer->registerTexture(textures[0].textureData,textures[0].m_width,textures[0].m_height); + + textureIndex = m_data->m_guiHelper->registerTexture(textures[0].textureData,textures[0].m_width,textures[0].m_height); } - graphicsIndex = renderer->registerShape(&vertices[0].xyzw[0], vertices.size(), &indices[0], indices.size(),B3_GL_TRIANGLES,textureIndex); + graphicsIndex = m_data->m_guiHelper->registerGraphicsShape(&vertices[0].xyzw[0], vertices.size(), &indices[0], indices.size(),B3_GL_TRIANGLES,textureIndex); } } diff --git a/examples/Importers/ImportURDFDemo/ImportURDFSetup.cpp b/examples/Importers/ImportURDFDemo/ImportURDFSetup.cpp index 92a917fd7..51b09e079 100644 --- a/examples/Importers/ImportURDFDemo/ImportURDFSetup.cpp +++ b/examples/Importers/ImportURDFDemo/ImportURDFSetup.cpp @@ -65,7 +65,8 @@ btAlignedObjectArray gFileNameArray; struct ImportUrdfInternalData { ImportUrdfInternalData() - :m_numMotors(0) + :m_numMotors(0), + m_mb(0) { for (int i=0;i