自由落体

#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;
}

 

posted @ 2014-03-24 08:46  20118281131  阅读(350)  评论(0编辑  收藏  举报