Historique des modifications - Message

Message #148

Sujet: C++ Irrlicht 1.1 et Ode 0.7 sous linux


Type Date Auteur Contenu
Création du message 11-10-2006 14:47:09 Copland
Salut, j'ai repris l'exemple de Kedu et moi même en .Net pour le passer sous irrlicht avec ode en c++ sous linux.
Bon ici y'a pas les gestion des threads car je ne maîtrise pas encore assez le C++ mais le code est pleinement fonctionnel.
Il vous faudra télécharger Ode 0.7 et le compiler pour essayer se code.

Code c++ :

#include <irrlicht.h>
#include <iostream>
#include <ode/ode.h>

using namespace irr;

//Parramètre de notre physique
dWorldID world = dWorldCreate();
dSpaceID space = dHashSpaceCreate (0);
dJointGroupID contactgroup = dJointGroupCreate (0);
dMass mass;
dBodyID body;
dGeomID geom;

//Proto de la méthode nearCallback
void nearCallback (void *data, dGeomID o1, dGeomID o2);
//Proto de la méthode updateEntitiesAfterPhysics
void updateEntitiesAfterPhysics(scene::ISceneNode* irrSceneNode,dGeomID geom);
//Proto de la méthode BtnClicked
bool BtnClicked(gui::IGUIButton* buton);

int main()
{
	//Creation du Device
	IrrlichtDevice* device = createDevice(video::EDT_OPENGL, core::dimension2d<s32>(800, 600),32,false,false,true);
	if (device == 0)
		return 1; // Si on ne peut pas creer le device avec ses drivers on quitte

    //On récupère les objets pour simplifier le code plus tard
	video::IVideoDriver* driver = device->getVideoDriver();
	scene::ISceneManager* smgr = device->getSceneManager();
    gui::IGUIEnvironment* env = device->getGUIEnvironment();

    //Chargement des médias
    video::ITexture* Tex = driver->getTexture("../media/wall.jpg");
    video::ITexture* Tex2 = driver->getTexture("../media/wall.bmp");

    //Modification d'une texture
    Tex->getTransformation().setScale(core::vector3df(300,300,300));

    //Creation de la camera
	scene::ICameraSceneNode* camera = smgr->addCameraSceneNode(NULL,core::vector3df(30,40,-82),core::vector3df(0,3,0),-1);

    //creation du mesh 3D de la sphere
    scene::ISceneNode* SphereSceneNode = smgr->addSphereSceneNode(5,32,NULL,1,core::vector3df(0,5.0f,-55));
    SphereSceneNode->setMaterialTexture(0,Tex2);
    SphereSceneNode->setMaterialFlag(video::EMF_LIGHTING,false);

    //Creation d'un plan 3D physique
    dCreatePlane (space,0,1,0,0);

    //initialisation des Body et Geom physique
    dBodyID Body[83];
    dGeomID Box[81];
    dGeomID Sphere;

    //Creation du body physique de la sphere
    Body[82] = dBodyCreate (world);
    dMassSetSphereTotal(&mass,6.0f,5);
    dBodySetMass(Body[82],&mass);
    dBodySetPosition(Body[82],0,5,-55);

    //Creation de la géométrie physique de la sphere
    Sphere = dCreateSphere(space, 5);
    dGeomSetBody(Sphere,Body[82]);

    //On va parramétrer la physique en même temps que la création de tout les cubes
    scene::ISceneNode* CubeSceneNode[81];
	s32 NbsCubeSceneNode=0;
    for (f32 y=0.0f;y<=40.0f;y+=5.0f)
    {
        for(f32 x=-40.0f+y;x<=40.0f-y;x+=5.0f)
        {
            //Creation des meshs des cubes
            CubeSceneNode[NbsCubeSceneNode] = smgr->addCubeSceneNode(5,NULL,-1,core::vector3df(x,y+2.5f,0));
            CubeSceneNode[NbsCubeSceneNode]->setMaterialTexture(0,Tex2);
            CubeSceneNode[NbsCubeSceneNode]->setMaterialFlag(video::EMF_LIGHTING,false);

            //Creation du Body physique des cubes
            Body[NbsCubeSceneNode] = dBodyCreate(world);
            dMassSetBoxTotal(&mass,5,5,5,5);
            dBodySetPosition(Body[NbsCubeSceneNode],x,y+2.5f,0);
            dBodySetAutoDisableFlag(Body[NbsCubeSceneNode],true);
            dBodyDisable(Body[NbsCubeSceneNode]);
            dBodySetAutoDisableLinearThreshold(Body[NbsCubeSceneNode],0.2);
            dBodySetAutoDisableAngularThreshold(Body[NbsCubeSceneNode],0.2);

            //Creation de la géométrie physique des cubes
            Box[NbsCubeSceneNode] = dCreateBox(space,5,5,5);
            dGeomSetBody(Box[NbsCubeSceneNode],Body[NbsCubeSceneNode]);

            //Incrémentation de la variable NbsCubeSceneNode
            NbsCubeSceneNode++;
        }
    }

    //On creer un mesh cubique qu'on applatira par le scale pour le sol
    scene::ISceneNode* SolSceneNode = smgr->addCubeSceneNode(10000,NULL,-1,core::vector3df(0,0,0));
    SolSceneNode->setMaterialTexture(0,Tex);
    SolSceneNode->setMaterialFlag(video::EMF_LIGHTING,false);
    SolSceneNode->setScale(core::vector3df(1,0.0f,1));

    //On ajoute un boutton pour expulser notre boule
    gui::IGUIButton* Buton = env->addButton(core::rect<s32>(10,10,120,35),NULL,100,L"Boum");

	//initialise la variable lastFPS
	int lastFPS = -1;

    //On parramètre la gravité de la physique et le nombre de frame qu'elle va saute pour les calculs
    dWorldSetGravity (world,0,-3,0);

	//Boucle principale
	while(device->run())
	if (device->isWindowActive())
	{
        //Calcul de notre physique
        dSpaceCollide (space, 0, &nearCallback);
        dWorldStepFast1(world,0.04f,1);
        dJointGroupEmpty(contactgroup);

        //On met à jour la boule en position + rotation grace à notre physique
	    updateEntitiesAfterPhysics(SphereSceneNode,Sphere);

        //On met à jour les cubes en position + rotation grace à notre physique
	    for (int i=0; i<81; i++)
	    {
	        updateEntitiesAfterPhysics(CubeSceneNode[i],Box[i]);
	    }

        //début des calculs d'irrlicht
		driver->beginScene(true, true, video::SColor(10,10,10,10));

        //On test si le bouton de la GUI est appuyé
        if (BtnClicked(Buton))
        {
            dBodyAddForce(Body[82],0,3000,10000);
        }

		//On dessine tout
		smgr->drawAll();

		//On dessine la GUI
		env->drawAll();

		//Fin des calculs d'irrlicht
		driver->endScene();

        //On récupère le FPS dans la variable fps
		int fps = driver->getFPS();

		//On affiche le fps dans la barre de titre
		if (lastFPS != fps)
		{
			core::stringw str = L"Irrlicht Engine with ODE [";
			str += driver->getName();
			str += "] FPS:";
			str += fps;

			device->setWindowCaption(str.c_str());
			lastFPS = fps;
		}
	}

	//On supprime le device d'irrlicht
	device->drop();

    //On supprime les groupes de joints de Ode
    dJointGroupEmpty (contactgroup);
    dJointGroupDestroy (contactgroup);

    //On supprime la géométrie de la sphère
    dGeomDestroy (Sphere);

    //On supprime les géométries des cubes
    for (int i=0;i<81;i++)
    {
        dGeomDestroy(Box[i]);
    }

    //On détruit l'espace d'ode
    dSpaceDestroy (space);

    //On détruit le monde d'ode
    dWorldDestroy (world);

    //retour 0 pour quitter
	return 0;
}

//La mise à jour de la physique se fait aussi par la mise à jour des objets
void updateEntitiesAfterPhysics(scene::ISceneNode* irrSceneNode,dGeomID geom)
{
	//Ici on met à jour la position
	irrSceneNode->setPosition(core::vector3df((f32)dGeomGetPosition(geom)[0],(f32)dGeomGetPosition(geom)[1],(f32)dGeomGetPosition(geom)[2]));

    //Un quaternion Ode pour les calculs de rotations
    dQuaternion result;

    //On écrit les rotations de ode dans le quaternion result
    dGeomGetQuaternion(geom,result);

    //Un quaternion Irrlicht pour convertir le quaternion de Ode
    core::quaternion quat;

    //On converti le quaternion de ode en quaternion Irrlicht
    quat.W = result[0];
    quat.X = result[1];
    quat.Y = result[2];
    quat.Z = result[3];

    //Vecteur Rot pour le calcul de la rotation
    core::vector3df Rot;

    //On bascule notre quaternion en vecteur d'angle euler
    quat.toEuler(Rot);

    //On converti de radian vers degré
    Rot.X = Rot.X / 3.14f * 180;
    Rot.Y = Rot.Y / 3.14f * 180;
    Rot.Z = Rot.Z / 3.14f * 180;

    //Ici on met à jour la rotation
    irrSceneNode->setRotation(Rot);
}

//Le fameux callBack de calcul pour la physique (merci les samples de ode)
void nearCallback (void *data, dGeomID o1, dGeomID o2)
{
  assert(o1);
  assert(o2);

  if (dGeomIsSpace(o1) || dGeomIsSpace(o2))
  {
    //Y'a-t-il une collision dans l'espace
    dSpaceCollide2(o1,o2,data,&nearCallback);
    return;
  }

  const int N = 32;
  dContact contact[N];
  int n = dCollide (o1,o2,N,&(contact[0].geom),sizeof(dContact));
  if (n > 0)
  {
    for (int i=0; i<n; i++)
    {
      contact[i].surface.slip1 = 0.7;
      contact[i].surface.slip2 = 0.7;
      contact[i].surface.mode = dContactSoftERP | dContactSoftCFM | dContactApprox1 | dContactSlip1 | dContactSlip2;
      contact[i].surface.mu = 50.0; // was: dInfinity
      contact[i].surface.soft_erp = 0.97;
      contact[i].surface.soft_cfm = 0.2;
      dJointID c = dJointCreateContact (world,contactgroup,&contact[i]);
      dJointAttach (c,dGeomGetBody(contact[i].geom.g1),dGeomGetBody(contact[i].geom.g2));
    }
  }
}

//Si on veut pas passer par les events ont peut bidouiller se genre de méthode
bool BtnClicked(gui::IGUIButton* buton)
{
    static bool AncienClic;

    if (AncienClic==true && buton->isPressed()==false)
    {
        AncienClic=buton->isPressed();
        return true;
    }
    else
    {
        AncienClic=buton->isPressed();
        return false;
    }
}

Voilou Bon code et @+

Retour

Options Liens officiels Caractéristiques Statistiques Communauté
Préférences cookies
Corrections
irrlicht
irrklang
irredit
irrxml
Propulsé par Django
xhtml 1.0
css 2.1
884 membres
1440 sujets
11337 messages
Dernier membre inscrit: Saidov17
132 invités en ligne
membre en ligne: -
RSS Feed