Files
bullet3/Demos3/bullet2/MultiBodyDemo/MultiBodyVehicle.cpp
erwin coumans 1e13454511 Added experimental implicit gyroscopic force implementation, one by Michael Ewert, and another by Cooper (from OpenDE)
Will also add Erin Catto's local implicit version from the GDC 2015 tutorial
Added demo for btGeneric6DofSpring2Constraint, thanks to Gabor Puhr
Add gfxBridge.autogenerateGraphicsObjects method for Bullet 2 demos in new framework (need to implement all Bullet 2 collision shape types...)
Use 1,1,1 for local scaling in btStaticPlaneShape
2015-03-24 15:55:05 -07:00

235 lines
7.6 KiB
C++

//test addJointTorque
#include "MultiBodyVehicle.h"
#include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h"
#include "BulletDynamics/Featherstone/btMultiBody.h"
#include "BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h"
#include "BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h"
#include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h"
#include "BulletDynamics/Featherstone/btMultiBodyLink.h"
#include "BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.h"
#include "BulletDynamics/Featherstone/btMultiBodyJointMotor.h"
#include "BulletDynamics/Featherstone/btMultiBodyPoint2Point.h"
#include "BulletCollision/CollisionShapes/btBoxShape.h"
btScalar gVehicleBaseMass = 100.f;
btScalar gVehicleWheelMass = 5.f;
float friction = 1.f;
btVector3 gVehicleBaseHalfExtents(1, 0.1, 2);
btVector3 gVehicleWheelHalfExtents(0.2, 0.2, 0.2);
btVector3 gVehicleWheelOffset(0, 0, 0.5);
btVector3 wheelAttachmentPosInWorld[4] = {
btVector3(1, 0, 2.),
btVector3(-1, 0, 2.),
btVector3(1, 0, -2.),
btVector3(-1, 0, -2.)
};
MultiBodyVehicleSetup::MultiBodyVehicleSetup()
{
}
MultiBodyVehicleSetup::~MultiBodyVehicleSetup()
{
}
class btMultiBody* MultiBodyVehicleSetup::createMultiBodyVehicle()
{
class btMultiBodyDynamicsWorld* world = m_dynamicsWorld;
int numWheels = 4;
int totalLinks = numWheels;//number of body parts (links) (in)directly attached to the base, NOT including the base/root itself
btCollisionShape* chassis = new btBoxShape(gVehicleBaseHalfExtents);//CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS));
m_collisionShapes.push_back(chassis);
btCollisionShape* wheel = new btCylinderShapeX(gVehicleWheelHalfExtents);//CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS,CUBE_HALF_EXTENTS));
m_collisionShapes.push_back(wheel);
btVector3 baseLocalInertia(0, 0, 0);
chassis->calculateLocalInertia(gVehicleBaseMass, baseLocalInertia);
bool multiDof = false;
bool isFixedBase = false;
bool canSleep = false;
btMultiBody * bod = new btMultiBody(totalLinks, gVehicleBaseMass, baseLocalInertia, isFixedBase, canSleep);// , multiDof);
bod->setHasSelfCollision(false);
btQuaternion baseOrn(0, 0, 0, 1);
btVector3 basePos(0, 0, 0);
bod->setBasePos(basePos);
bod->setWorldToBaseRot(baseOrn);
btVector3 vel(0, 0, 0);
bod->setBaseVel(vel);
{
int linkNum = 0;
btVector3 wheelJointAxisWorld(1, 0, 0);
btQuaternion parent_to_child = baseOrn.inverse();//??
for (int j = 0; j < numWheels; j++, linkNum++)
{
int parent_link_num = -1;
float initial_joint_angle = 0.0;
btVector3 localWheelInertia(0, 0, 0);
wheel->calculateLocalInertia(gVehicleWheelMass, localWheelInertia);
bool disableParentCollision = true;
btVector3 pivotToChildCOM(0, 0, 0.25);
btVector3 pivotToWheelCOM(0, 0, 0);
{
bod->setupRevolute(linkNum, gVehicleWheelMass, localWheelInertia, parent_link_num, parent_to_child, wheelJointAxisWorld,
wheelAttachmentPosInWorld[j], pivotToWheelCOM, disableParentCollision);
}
bod->setJointPos(linkNum, initial_joint_angle);
if (j<2)
{
btMultiBodyJointMotor* con = new btMultiBodyJointMotor(bod, linkNum, 1., 50);
world->addMultiBodyConstraint(con);
}
}
}
//add a collider for the base
{
btAlignedObjectArray<btQuaternion> world_to_local;
world_to_local.resize(totalLinks + 1);
btAlignedObjectArray<btVector3> local_origin;
local_origin.resize(totalLinks + 1);
world_to_local[0] = bod->getWorldToBaseRot();
local_origin[0] = bod->getBasePos();
{
float pos[4] = { local_origin[0].x(), local_origin[0].y(), local_origin[0].z(), 1 };
float quat[4] = { -world_to_local[0].x(), -world_to_local[0].y(), -world_to_local[0].z(), world_to_local[0].w() };
if (1)
{
btMultiBodyLinkCollider* col = new btMultiBodyLinkCollider(bod, -1);
col->setCollisionShape(chassis);
btTransform tr;
tr.setIdentity();
tr.setOrigin(local_origin[0]);
tr.setRotation(btQuaternion(quat[0], quat[1], quat[2], quat[3]));
col->setWorldTransform(tr);
world->addCollisionObject(col, btBroadphaseProxy::DefaultFilter, btBroadphaseProxy::AllFilter);// 2, 1 + 2);
col->setFriction(friction);
bod->setBaseCollider(col);
}
}
//initialize local coordinate frames, relative to parent
for (int i = 0; i<bod->getNumLinks(); i++)
{
const int parent = bod->getParent(i);
world_to_local[i + 1] = bod->getParentToLocalRot(i) * world_to_local[parent + 1];
local_origin[i + 1] = local_origin[parent + 1] + (quatRotate(world_to_local[i + 1].inverse(), bod->getRVector(i)));
}
int linkIndex = 0;
for (int j = 0; j<numWheels; j++, linkIndex++)
{
btVector3 posr = local_origin[linkIndex + 1];
float pos[4] = { posr.x(), posr.y(), posr.z(), 1 };
float quat[4] = { -world_to_local[linkIndex + 1].x(), -world_to_local[linkIndex + 1].y(), -world_to_local[linkIndex + 1].z(), world_to_local[linkIndex + 1].w() };
btMultiBodyLinkCollider* col = new btMultiBodyLinkCollider(bod, linkIndex);
col->setCollisionShape(wheel);
btTransform tr;
tr.setIdentity();
tr.setOrigin(posr);
tr.setRotation(btQuaternion(quat[0], quat[1], quat[2], quat[3]));
col->setWorldTransform(tr);
col->setFriction(friction);
world->addCollisionObject(col, btBroadphaseProxy::DefaultFilter, btBroadphaseProxy::AllFilter);// 2, 1 + 2);
bod->getLink(linkIndex).m_collider = col;
}
}
world->addMultiBody(bod);
// world->setGravity(btVector3(0,0,0));
return bod;
}
void MultiBodyVehicleSetup::initPhysics(GraphicsPhysicsBridge& gfxBridge)
{
int upAxis = 1;
btVector4 colors[4] =
{
btVector4(1,0,0,1),
btVector4(0,1,0,1),
btVector4(0,1,1,1),
btVector4(1,1,0,1),
};
int curColor = 0;
gfxBridge.setUpAxis(upAxis);
this->createEmptyDynamicsWorld();
gfxBridge.createPhysicsDebugDrawer(m_dynamicsWorld);
m_dynamicsWorld->getDebugDrawer()->setDebugMode(
//btIDebugDraw::DBG_DrawConstraints
+btIDebugDraw::DBG_DrawWireframe
+btIDebugDraw::DBG_DrawContactPoints
+btIDebugDraw::DBG_DrawAabb
);//+btIDebugDraw::DBG_DrawConstraintLimits);
createMultiBodyVehicle();
if (1)
{
btVector3 groundHalfExtents(20,20,20);
groundHalfExtents[upAxis]=1.f;
btBoxShape* box = new btBoxShape(groundHalfExtents);
box->initializePolyhedralFeatures();
btTransform start; start.setIdentity();
btVector3 groundOrigin(0,0,0);
groundOrigin[upAxis]=-1.5;
start.setOrigin(groundOrigin);
btRigidBody* body = createRigidBody(0,start,box);
}
gfxBridge.autogenerateGraphicsObjects(m_dynamicsWorld);
}
void MultiBodyVehicleSetup::stepSimulation(float deltaTime)
{
m_dynamicsWorld->stepSimulation(deltaTime);
}