summaryrefslogtreecommitdiff
path: root/examples/DeformableDemo/VolumetricDeformable.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'examples/DeformableDemo/VolumetricDeformable.cpp')
-rw-r--r--examples/DeformableDemo/VolumetricDeformable.cpp296
1 files changed, 296 insertions, 0 deletions
diff --git a/examples/DeformableDemo/VolumetricDeformable.cpp b/examples/DeformableDemo/VolumetricDeformable.cpp
new file mode 100644
index 000000000..74d9678a8
--- /dev/null
+++ b/examples/DeformableDemo/VolumetricDeformable.cpp
@@ -0,0 +1,296 @@
+/*
+ Bullet Continuous Collision Detection and Physics Library
+ Copyright (c) 2019 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.
+ */
+
+///create 125 (5x5x5) dynamic object
+#define ARRAY_SIZE_X 5
+#define ARRAY_SIZE_Y 5
+#define ARRAY_SIZE_Z 5
+
+//maximum number of objects (and allow user to shoot additional boxes)
+#define MAX_PROXIES (ARRAY_SIZE_X * ARRAY_SIZE_Y * ARRAY_SIZE_Z + 1024)
+
+///scaling of the objects (0.1 = 20 centimeter boxes )
+#define SCALING 1.
+#define START_POS_X -5
+#define START_POS_Y -5
+#define START_POS_Z -3
+
+#include "VolumetricDeformable.h"
+///btBulletDynamicsCommon.h is the main Bullet include file, contains most common include files.
+#include "btBulletDynamicsCommon.h"
+#include "BulletSoftBody/btDeformableRigidDynamicsWorld.h"
+#include "BulletSoftBody/btSoftBody.h"
+#include "BulletSoftBody/btSoftBodyHelpers.h"
+#include "BulletSoftBody/btDeformableBodySolver.h"
+#include "BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h"
+#include "BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h"
+#include <stdio.h> //printf debugging
+
+#include "../CommonInterfaces/CommonRigidBodyBase.h"
+#include "../Utils/b3ResourcePath.h"
+
+///The VolumetricDeformable shows the use of rolling friction.
+///Spheres will come to a rest on a sloped plane using a constraint. Damping cannot achieve the same.
+///Generally it is best to leave the rolling friction coefficient zero (or close to zero).
+
+
+struct TetraCube
+{
+#include "../SoftDemo/cube.inl"
+};
+
+class VolumetricDeformable : public CommonRigidBodyBase
+{
+public:
+ VolumetricDeformable(struct GUIHelperInterface* helper)
+ : CommonRigidBodyBase(helper)
+ {
+ }
+ virtual ~VolumetricDeformable()
+ {
+ }
+ void initPhysics();
+
+ void exitPhysics();
+
+ void resetCamera()
+ {
+ float dist = 20;
+ float pitch = -45;
+ float yaw = 100;
+ float targetPos[3] = {0, 3, 0};
+ m_guiHelper->resetCamera(dist, yaw, pitch, targetPos[0], targetPos[1], targetPos[2]);
+ }
+
+ void stepSimulation(float deltaTime)
+ {
+ //use a smaller internal timestep, there are stability issues
+ float internalTimeStep = 1. / 240.f;
+ m_dynamicsWorld->stepSimulation(deltaTime, 4, internalTimeStep);
+ }
+
+ void createStaticBox(const btVector3& halfEdge, const btVector3& translation)
+ {
+ btCollisionShape* box = new btBoxShape(halfEdge);
+ m_collisionShapes.push_back(box);
+
+ btTransform Transform;
+ Transform.setIdentity();
+ Transform.setOrigin(translation);
+ Transform.setRotation(btQuaternion(btVector3(1, 0, 0), SIMD_PI * 0.0));
+ //We can also use DemoApplication::localCreateRigidBody, but for clarity it is provided here:
+ btScalar mass(0.);
+ //rigidbody is dynamic if and only if mass is non zero, otherwise static
+ bool isDynamic = (mass != 0.f);
+ btVector3 localInertia(0, 0, 0);
+ if (isDynamic)
+ box->calculateLocalInertia(mass, localInertia);
+ //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
+ btDefaultMotionState* myMotionState = new btDefaultMotionState(Transform);
+ btRigidBody::btRigidBodyConstructionInfo rbInfo(mass, myMotionState, box, localInertia);
+ btRigidBody* body = new btRigidBody(rbInfo);
+ body->setFriction(0.5);
+
+ //add the ground to the dynamics world
+ m_dynamicsWorld->addRigidBody(body);
+ }
+
+ void Ctor_RbUpStack(int count)
+ {
+ float mass = 0.02;
+
+ btCompoundShape* cylinderCompound = new btCompoundShape;
+ btCollisionShape* cylinderShape = new btCylinderShapeX(btVector3(2, .5, .5));
+ btCollisionShape* boxShape = new btBoxShape(btVector3(2, .5, .5));
+ btTransform localTransform;
+ localTransform.setIdentity();
+ cylinderCompound->addChildShape(localTransform, boxShape);
+ btQuaternion orn(SIMD_HALF_PI, 0, 0);
+ localTransform.setRotation(orn);
+ // localTransform.setOrigin(btVector3(1,1,1));
+ cylinderCompound->addChildShape(localTransform, cylinderShape);
+
+ btCollisionShape* shape[] = {
+ new btBoxShape(btVector3(1, 1, 1)),
+ };
+ static const int nshapes = sizeof(shape) / sizeof(shape[0]);
+ for (int i = 0; i < count; ++i)
+ {
+ btTransform startTransform;
+ startTransform.setIdentity();
+ startTransform.setOrigin(btVector3(i, 10 + 2 * i, i-1));
+ createRigidBody(mass, startTransform, shape[i % nshapes]);
+ }
+ }
+
+ virtual const btDeformableRigidDynamicsWorld* getDeformableDynamicsWorld() const
+ {
+ ///just make it a btSoftRigidDynamicsWorld please
+ ///or we will add type checking
+ return (btDeformableRigidDynamicsWorld*)m_dynamicsWorld;
+ }
+
+ virtual btDeformableRigidDynamicsWorld* getDeformableDynamicsWorld()
+ {
+ ///just make it a btSoftRigidDynamicsWorld please
+ ///or we will add type checking
+ return (btDeformableRigidDynamicsWorld*)m_dynamicsWorld;
+ }
+
+ virtual void renderScene()
+ {
+ CommonRigidBodyBase::renderScene();
+ btDeformableRigidDynamicsWorld* deformableWorld = getDeformableDynamicsWorld();
+
+ for (int i = 0; i < deformableWorld->getSoftBodyArray().size(); i++)
+ {
+ btSoftBody* psb = (btSoftBody*)deformableWorld->getSoftBodyArray()[i];
+ //if (softWorld->getDebugDrawer() && !(softWorld->getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe)))
+ {
+ btSoftBodyHelpers::DrawFrame(psb, deformableWorld->getDebugDrawer());
+ btSoftBodyHelpers::Draw(psb, deformableWorld->getDebugDrawer(), deformableWorld->getDrawFlags());
+ }
+ }
+ }
+};
+
+void VolumetricDeformable::initPhysics()
+{
+ m_guiHelper->setUpAxis(1);
+
+ ///collision configuration contains default setup for memory, collision setup
+ m_collisionConfiguration = new btSoftBodyRigidBodyCollisionConfiguration();
+
+ ///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded)
+ m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
+
+ m_broadphase = new btDbvtBroadphase();
+ btDeformableBodySolver* deformableBodySolver = new btDeformableBodySolver();
+
+ ///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded)
+ btMultiBodyConstraintSolver* sol = new btMultiBodyConstraintSolver();
+ m_solver = sol;
+
+ m_dynamicsWorld = new btDeformableRigidDynamicsWorld(m_dispatcher, m_broadphase, sol, m_collisionConfiguration, deformableBodySolver);
+ deformableBodySolver->setWorld(getDeformableDynamicsWorld());
+ // m_dynamicsWorld->getSolverInfo().m_singleAxisDeformableThreshold = 0.f;//faster but lower quality
+ btVector3 gravity = btVector3(0, -10, 0);
+ m_dynamicsWorld->setGravity(gravity);
+ getDeformableDynamicsWorld()->getWorldInfo().m_gravity = gravity;
+ m_guiHelper->createPhysicsDebugDrawer(m_dynamicsWorld);
+
+ {
+ ///create a ground
+ btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(150.), btScalar(50.), btScalar(150.)));
+ m_collisionShapes.push_back(groundShape);
+
+ btTransform groundTransform;
+ groundTransform.setIdentity();
+ groundTransform.setOrigin(btVector3(0, -50, 0));
+ groundTransform.setRotation(btQuaternion(btVector3(1, 0, 0), SIMD_PI * 0.0));
+ //We can also use DemoApplication::localCreateRigidBody, but for clarity it is provided here:
+ btScalar mass(0.);
+ //rigidbody is dynamic if and only if mass is non zero, otherwise static
+ bool isDynamic = (mass != 0.f);
+ btVector3 localInertia(0, 0, 0);
+ if (isDynamic)
+ groundShape->calculateLocalInertia(mass, localInertia);
+ //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
+ btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform);
+ btRigidBody::btRigidBodyConstructionInfo rbInfo(mass, myMotionState, groundShape, localInertia);
+ btRigidBody* body = new btRigidBody(rbInfo);
+ body->setFriction(0.5);
+
+ //add the ground to the dynamics world
+ m_dynamicsWorld->addRigidBody(body);
+ }
+
+ createStaticBox(btVector3(1, 5, 5), btVector3(-5,0,0));
+ createStaticBox(btVector3(1, 5, 5), btVector3(5,0,0));
+ createStaticBox(btVector3(5, 5, 1), btVector3(0,0,5));
+ createStaticBox(btVector3(5, 5, 1), btVector3(0,0,-5));
+
+ // create volumetric soft body
+ {
+ btSoftBody* psb = btSoftBodyHelpers::CreateFromTetGenData(getDeformableDynamicsWorld()->getWorldInfo(),
+ TetraCube::getElements(),
+ 0,
+ TetraCube::getNodes(),
+ false, true, true);
+ getDeformableDynamicsWorld()->addSoftBody(psb);
+ psb->scale(btVector3(2, 2, 2));
+ psb->translate(btVector3(0, 5, 0));
+// psb->setVolumeMass(10);
+ psb->getCollisionShape()->setMargin(0.25);
+// psb->generateBendingConstraints(2);
+ psb->setTotalMass(1);
+ psb->setSpringStiffness(1);
+ psb->setDampingCoefficient(0.01);
+ psb->m_cfg.kKHR = 1; // collision hardness with kinematic objects
+ psb->m_cfg.kCHR = 1; // collision hardness with rigid body
+ psb->m_cfg.kDF = 0.5;
+ psb->m_cfg.collisions = btSoftBody::fCollision::SDF_RD;
+ getDeformableDynamicsWorld()->addForce(psb, new btDeformableMassSpringForce());
+ getDeformableDynamicsWorld()->addForce(psb, new btDeformableGravityForce(gravity));
+ }
+ // add a few rigid bodies
+ Ctor_RbUpStack(4);
+
+ m_guiHelper->autogenerateGraphicsObjects(m_dynamicsWorld);
+}
+
+void VolumetricDeformable::exitPhysics()
+{
+ //cleanup in the reverse order of creation/initialization
+
+ //remove the rigidbodies from the dynamics world and delete them
+ int i;
+ for (i = m_dynamicsWorld->getNumCollisionObjects() - 1; i >= 0; i--)
+ {
+ btCollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[i];
+ btRigidBody* body = btRigidBody::upcast(obj);
+ if (body && body->getMotionState())
+ {
+ delete body->getMotionState();
+ }
+ m_dynamicsWorld->removeCollisionObject(obj);
+ delete obj;
+ }
+
+ //delete collision shapes
+ for (int j = 0; j < m_collisionShapes.size(); j++)
+ {
+ btCollisionShape* shape = m_collisionShapes[j];
+ delete shape;
+ }
+ m_collisionShapes.clear();
+
+ delete m_dynamicsWorld;
+
+ delete m_solver;
+
+ delete m_broadphase;
+
+ delete m_dispatcher;
+
+ delete m_collisionConfiguration;
+}
+
+
+
+class CommonExampleInterface* VolumetricDeformableCreateFunc(struct CommonExampleOptions& options)
+{
+ return new VolumetricDeformable(options.m_guiHelper);
+}
+
+