自由落体
#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; }