7 de out. de 2009

Exmplo OSG+PhysX

//--------------------------

//Autor: Tiago buriol
//---------------------------


// C++ includes
#include < stdio.h >
#include < sys/time.h >

// OSG includes
#include < osgViewer/Viewer >
#include < osg/Geometry >
#include < osgGA/TrackballManipulator >
#include < osg/Vec3d >
#include < osg/PositionAttitudeTransform >
#include < osg/ShapeDrawable >

// PhysX include
#include "NxPhysics.h"

// Declaracao de variaveis globais para o PhysX
static NxPhysicsSDK*    gPhysicsSDK = NULL;
static NxScene*            gScene = NULL;

NxActor* box = NULL;

// Inicializa o Physx e define alguns parametros
static bool InitNx()
{
    // Inicializa o PhysX SDK
    NxPhysicsSDKDesc desc;

    gPhysicsSDK = NxCreatePhysicsSDK(NX_PHYSICS_SDK_VERSION);
        if (!gPhysicsSDK)  return false;
        gPhysicsSDK->setParameter(NX_SKIN_WIDTH, 0.001);

    // Cria uma cena
    NxSceneDesc sceneDesc;
        //sceneDesc.simType = NX_SIMULATION_HW;
        sceneDesc.simType = NX_SIMULATION_SW;
        sceneDesc.gravity = NxVec3(0.0f, -9.81f, 0.0f);

    gScene = gPhysicsSDK->createScene(sceneDesc);

    // Set default material
    NxMaterial* defaultMaterial = gScene->getMaterialFromIndex(0);
        defaultMaterial->setRestitution(0.2f);
        defaultMaterial->setStaticFriction(0.01f);
        defaultMaterial->setDynamicFriction(0.01f);

    // Create ground plane
    NxPlaneShapeDesc planeDesc;
        //planeDesc.skinWidth = 0.01f;
    NxActorDesc actorDesc;
        actorDesc.shapes.pushBack(&planeDesc);
        actorDesc.globalPose.t = NxVec3(0.0, 0.0, 0.0);
    gScene->createActor(actorDesc);

    // Add a single-shape actor to the scene
    NxActorDesc boxActorDesc;
    NxBodyDesc boxBodyDesc;

    // The actor has one shape, a box, 1m on a side
    NxBoxShapeDesc boxDesc;
    boxDesc.dimensions.set(1.0, 1.0, 1.0);
    //boxDesc.skinWidth = 0.01f;
    boxActorDesc.shapes.pushBack(&boxDesc);
    boxActorDesc.body        = & boxBodyDesc;
    boxActorDesc.density     = 5.0f;
    boxActorDesc.globalPose.M.fromQuat(NxQuat(30.0, NxVec3(1, 0, 0)));
    boxActorDesc.globalPose.t     = NxVec3(0,5.0,0);

    box = gScene->createActor(boxActorDesc);

    //printf("altura %f\n",box->getGlobalPosition().y);
    return true;
}

int main(int argc, char** argv)
{
      double delta_t;
      struct timeval tv1, tv2;

      // Cria o visualizador
      osgViewer::Viewer viewer;
      osg::ref_ptr root = new osg::Group;

      osg::Sphere* unitSphere = new osg::Sphere(osg::Vec3(0,0,0), 1.0);
      osg::ShapeDrawable* unitSphereDrawable = new osg::ShapeDrawable(unitSphere);
          unitSphereDrawable->setColor(osg::Vec4(1, 0, 0, 1));
      osg::Geode* unitSphereGeode = new osg::Geode();
          unitSphereGeode->addDrawable(unitSphereDrawable);
      osg::PositionAttitudeTransform* unitSpherePAT = new osg::PositionAttitudeTransform();
          unitSpherePAT->setPosition(osg::Vec3(2.0,0.0,1.0));
          unitSpherePAT->addChild(unitSphereGeode);

      // Cria o cubo a ser renderizado
      osg::Box* unitBox = new osg::Box(osg::Vec3(0,0,-0.5), 1.0, 1.0, 1.0);
      osg::ShapeDrawable* unitBoxDrawable = new osg::ShapeDrawable(unitBox);
          unitBoxDrawable->setColor(osg::Vec4(1, 1, 0, 1));
      osg::Geode* unitBoxGeode = new osg::Geode();
          unitBoxGeode->addDrawable(unitBoxDrawable);
      osg::PositionAttitudeTransform* unitBoxPAT = new osg::PositionAttitudeTransform();
          unitBoxPAT->addChild(unitBoxGeode);

      // Desenha um plano
       osg::Vec3 coords[] = { osg::Vec3(-3.0, 3.0, -0.01),
                             osg::Vec3(3.0, 3.0, -0.01),
                             osg::Vec3(3.0, -3.0, -0.01),
                             osg::Vec3(-3.0, -3.0, -0.01)
                           };
      osg::Vec3Array* vertices = new osg::Vec3Array(4,coords);
      osg::Geometry* planeGeometry = new osg::Geometry();
          planeGeometry->setVertexArray(vertices);
          planeGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4));
      osg::Vec4Array* colors = new osg::Vec4Array;
          colors->push_back(osg::Vec4(0.8f,0.8f,1.0f,1.0f));
          planeGeometry->setColorArray(colors);
          planeGeometry->setColorBinding(osg::Geometry::BIND_OVERALL);
      osg::Vec3Array *shared_normals = new osg::Vec3Array;
          shared_normals->push_back(osg::Vec3(0.0f,-1.0f,0.0f));
          // use the shared normal array.
          planeGeometry->setNormalArray(shared_normals);
          planeGeometry->setNormalBinding(osg::Geometry::BIND_OVERALL);
      osg::Geode* planeGeode = new osg::Geode();
             planeGeode->addDrawable(planeGeometry);

      root->addChild(unitSpherePAT);
      root->addChild(unitBoxPAT);
      root->addChild(planeGeode);

      viewer.setSceneData(root.get());
      viewer.setUpViewInWindow(0, 0, 800, 600);
      viewer.setCameraManipulator(new osgGA::TrackballManipulator());
      viewer.realize();

      // Initialize physics scene and start the application main loop if scene was created
      if (InitNx())
      delta_t = 0.001;

      // Loop principal da simulacao
      while (!viewer.done()) {

        // Pega o tempo inicial
        gettimeofday(&tv1, NULL);

            // Realiza um passo da simulacao para um intervalo de tempo igual a delta_t
            gScene->simulate((NxReal)delta_t);
            gScene->flushStream();
            gScene->fetchResults(NX_RIGID_BODY_FINISHED, false);

            // Sincroniza as posicao e rotacao dos cubos simulado e renderizado
            unitBoxPAT->setAttitude(osg::Quat(box->getGlobalOrientationQuat().x,
                                              box->getGlobalOrientationQuat().z,
                                              box->getGlobalOrientationQuat().y,
                                              box->getGlobalOrientationQuat().w) );
            unitBoxPAT->setPosition(osg::Vec3d(box->getGlobalPosition().x,
                                               box->getGlobalPosition().z,
                                               box->getGlobalPosition().y) );
            // Atualiza o frame
            viewer.frame();

        // Pega o tempo final e calcula o tempo entre um frame e outro
        gettimeofday(&tv2, NULL);
        delta_t = (tv2.tv_usec - tv1.tv_usec)*0.000001;
      }

    return 0;
}