#include <osgViewer/Viewer>
#include <osg/MatrixTransform>
#include <osg/ShapeDrawable>
#include <btBulletDynamicsCommon.h>
#include <btBulletCollisionCommon.h>
#include <osgDB/ReadFile>
#include <iostream>
#pragma comment(lib, "osgd.lib")
#pragma comment(lib, "osgViewerd.lib")
#pragma comment(lib, "osgDBd.lib")
#pragma comment(lib, "osgGAd.lib")
#pragma comment(lib, "BulletCollision_vs2010_debug.lib")
#pragma comment(lib, "BulletDynamics_vs2010_debug.lib")
#pragma comment(lib, "ConvexDecomposition_vs2010_debug.lib")
#pragma comment(lib, "HACD_vs2010_debug.lib")
#pragma comment(lib, "LinearMath_vs2010_debug.lib")
#pragma comment(lib, "OpenGLSupport_vs2010_debug.lib")
class CBtWorld : public osg::Referenced
{
public:
CBtWorld()
{
_collisionConfiguration = new btDefaultCollisionConfiguration;
_dispatcher = new btCollisionDispatcher(_collisionConfiguration);
_overlappingPairCache = new btDbvtBroadphase;
_solver = new btSequentialImpulseConstraintSolver;
_world = new btDiscreteDynamicsWorld(_dispatcher, _overlappingPairCache, _solver, _collisionConfiguration);
}
~CBtWorld()
{
if (_collisionConfiguration != NULL)
{
delete _collisionConfiguration;
}
if (_dispatcher != NULL)
{
delete _dispatcher;
}
if (_overlappingPairCache != NULL)
{
delete _overlappingPairCache;
}
if (_solver != NULL)
{
delete _solver;
}
if (_world != NULL)
{
delete _world;
}
}
public:
void SetGravity(osg::Vec3 & v)
{
_world->setGravity(btVector3(v._v[0], v._v[1], v._v[2]));
}
btAlignedObjectArray<btCollisionShape *> GetShapeArray()
{
return _shapeArray;
}
btDiscreteDynamicsWorld * GetWorld()
{
return _world;
}
void AddRigidBody(btRigidBody * body)
{
_world->addRigidBody(body);
}
protected:
btDefaultCollisionConfiguration * _collisionConfiguration;
btCollisionDispatcher * _dispatcher;
btBroadphaseInterface * _overlappingPairCache;
btSequentialImpulseConstraintSolver * _solver;
btDiscreteDynamicsWorld * _world;
btAlignedObjectArray<btCollisionShape *> _shapeArray;
};
class CShape : public osg::MatrixTransform
{
public:
CShape()
{
_btWorld->SetGravity(osg::Vec3(0.0, -10.0, 0.0));
}
protected:
virtual void Init() = 0;
virtual void InitPhysx() = 0;
public:
static osg::ref_ptr<CBtWorld> _btWorld;
protected:
osg::ref_ptr<osg::Geode> _geode;
};
osg::ref_ptr<CBtWorld> CShape::_btWorld = new CBtWorld;
class CPlane : public CShape
{
public:
CPlane()
:CShape()
{
Init();
InitPhysx();
}
virtual void Init()
{
_geode = new osg::Geode;
osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
osg::ref_ptr<osg::Vec3Array> vArray = new osg::Vec3Array;
vArray->push_back(osg::Vec3(-50.0, -56.0, -50.0));
vArray->push_back(osg::Vec3(50.0, -56, -50.0));
vArray->push_back(osg::Vec3(50.0, -56, 50.0));
vArray->push_back(osg::Vec3(-50.0, -56, 50.0));
geometry->setVertexArray(vArray.get());
geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, vArray->size()));
_geode->addDrawable(geometry.get());
addChild(_geode.get());
}
virtual void InitPhysx()
{
btCollisionShape * _collisionShape = new btStaticPlaneShape(btVector3(0.0, 1.0, 0.0), 1.0);
_btWorld->GetShapeArray().push_back(_collisionShape);
btTransform groundTransform;
groundTransform.setIdentity();
groundTransform.setOrigin(btVector3(0,-58,0));
btScalar mass(0.0);
bool isDynamic = (mass != 0.f);
btVector3 localInertia(0,0,0);
//if (isDynamic)
_collisionShape->calculateLocalInertia(mass,localInertia);
btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform);
btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,_collisionShape,localInertia);
btRigidBody* body = new btRigidBody(rbInfo);
_btWorld->AddRigidBody(body);
}
};
class CBall : public CShape
{
public:
CBall()
:CShape()
{
Init();
InitPhysx();
setName("Ball");
}
protected:
virtual void Init()
{
_geode = new osg::Geode;
osg::ref_ptr<osg::ShapeDrawable> shapeDrawable = new osg::ShapeDrawable;
osg::ref_ptr<osg::Sphere> sphere = new osg::Sphere(osg::Vec3(0.0, 1.0, 0.0), 1);
shapeDrawable->setShape(sphere.get());
_geode->addDrawable(shapeDrawable.get());
addChild(_geode.get());
}
virtual void InitPhysx()
{
btCollisionShape* colShape = new btSphereShape(btScalar(1.));
_btWorld->GetShapeArray().push_back(colShape);
btTransform startTransform;
startTransform.setIdentity();
btScalar mass(1.f);
bool isDynamic = (mass != 0.f);
btVector3 localInertia(0,0,0);
if (isDynamic)
colShape->calculateLocalInertia(mass,localInertia);
startTransform.setOrigin(btVector3(2, 10, 0));
btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform);
btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,colShape,localInertia);
btRigidBody* body = new btRigidBody(rbInfo);
_btWorld->AddRigidBody(body);
}
};
class SimulationCallback : public osg::NodeCallback
{
public:
SimulationCallback()
:_flag(0)
,_temp(100)
{
}
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
{
if (_temp == _flag+1)
{
_flag = 0;
if (node->getName() == "Ball")
{
osg::MatrixTransform * matrixTransform = dynamic_cast<osg::MatrixTransform *>(node);
CShape::_btWorld->GetWorld()->stepSimulation(1.f/60.f,10);
for (int j=CShape::_btWorld->GetWorld()->getNumCollisionObjects()-1; j>=0 ;j--)
{
btCollisionObject* obj = CShape::_btWorld->GetWorld()->getCollisionObjectArray()[1];
btRigidBody* body = btRigidBody::upcast(obj);
if (body && body->getMotionState())
{
btTransform trans;
body->getMotionState()->getWorldTransform(trans);
matrixTransform->setMatrix(osg::Matrix::translate(trans.getOrigin().x(), trans.getOrigin().y(), trans.getOrigin().z()));
std::cout << trans.getOrigin().x() << "," << trans.getOrigin().z() << "," << trans.getOrigin().y() << std::endl;
}
}
}
}
_flag++;
traverse(node,nv);
}
private:
int _flag;
int _temp;
};
int main()
{
osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;
osg::ref_ptr<CPlane> plane = new CPlane;
osg::ref_ptr<CBall> ball = new CBall;
osg::ref_ptr<osg::Group> root = new osg::Group;
root->addChild(plane.get());
root->addChild(ball.get());
ball->setUpdateCallback(new SimulationCallback);
viewer->setSceneData(root.get());
viewer->run();
for (int i = CShape::_btWorld->GetWorld()->getNumCollisionObjects()-1; i>=0 ;i--)
{
btCollisionObject* obj = CShape::_btWorld->GetWorld()->getCollisionObjectArray()[i];
btRigidBody* body = btRigidBody::upcast(obj);
if (body && body->getMotionState())
{
delete body->getMotionState();
}
CShape::_btWorld->GetWorld()->removeCollisionObject( obj );
delete obj;
}
for (int j=0;j< CShape::_btWorld->GetShapeArray().size();j++)
{
btCollisionShape* shape = CShape::_btWorld->GetShapeArray()[j];
CShape::_btWorld->GetShapeArray()[j] = 0;
delete shape;
}
return 0;
}