Historique des modifications - Message

Message #125

Sujet: [C# - Irrlicht.net - ODE.net] Intégrer de la physique dans Irrlicht !


Type Date Auteur Contenu
Dernière modification 28-10-2006 07:42:52 kedu
Ce tuto s'adresse aux débutants avant tout ; le but étant de montrer une manière d'intégrer la physique avec votre moteur graphique favori !
Vous trouverez à la fin l'ensemble du code source en rapport avec cette petite scène. Les dll d'ODE et D'Irrlicht s'y trouvent volontairement au cas où vous ayez besoin de les remettre en réfèrences du projet.


L'objectif de ce tutorial est de mettre au point une petite scène constituée d'un sol, d'un mur de brique et d'une balle ! Un bouton permettra d'appliquer une force à la balle afin que cette dernière percute le mur de brique. Tout un programme !



I) La partie graphique

Rien de difficile ici, nous faisons juste appel au passage à une fenêtre qui nous permet de recueillir les souhaits pour le paramétrage du driver d'Irrlicht. (choix de la résolution, du type de driver, etc.)

Je vous laisse vous reporter au contenu de cette "SetupDriverDialog" qui est on ne peut plus basique.

//Initialisation du driver video
SetupDriverDialog DriverDialog = new SetupDriverDialog();
DriverDialog.ShowDialog();

Voyons maintenant quelque chose de plus intéressant : nous avons initialisé la 3D, il serait peut être temps de penser à la physique !

//Initialisation et lancement de la physique
maPhysique = new Physique();
monThreadDeRenduPhysique = new Thread(new ThreadStart (maPhysique.PhysiqueRenderLoop));
monThreadDeRenduPhysique.Start();

Nous détaillerons dans la partie suivante cette classe qui gère notre physique. Néanmoins on voit ici que l'exécution de cette physique se fait dans un thread à part.

Voici les raisons qui expliquent ce choix :
  • Nous évitons ici de calculer la physique dans notre boucle de rendu 3D d'Irrlicht. Cela n'est pas innocent ; ainsi une mauvaise performance dans le rendu 3D n'influera pas dans le calcul de notre physique. (et l'inverse est aussi vrai)
  • Une autre raison réside dans le fait que nous devons bénéficier d'une "unité de temps" pour notre scène. (vous trouverez l'explication à cela dans la seconde partie)


Pour clore cette première partie, il nous reste à peupler notre scene d'un sol, d'un mur de cubes, d'une balle. A titre d'exemple voici le code de notre mur de cubes :
int NbsCubeSceneNode=0;
for (float y=0.0f;y<=40.0f;y+=5.0f)
{
  for(float x=-40f+y;x<=40f-y;x+=5f)
  {
  CubeSceneNode[NbsCubeSceneNode] = device.SceneManager.AddCubeSceneNode(5,null,-1,new Vector3D(x,y+2.5f,0));
  CubeSceneNode[NbsCubeSceneNode].SetMaterialTexture(0, device.VideoDriver.GetTexture("cube.jpg"));CubeSceneNode[NbsCubeSceneNode].SetMaterialFlag(MaterialFlag.LIGHTING, false);
  NbsCubeSceneNode++;
  }
}

Rien de bien compliqué, il suffit juste d'apprécier la magie d'Irrlicht...

II) La physique

C'est bien entendu ici que réside la difficulté... Par où commencer ? Et bien nous avons deux choses à mettre en place rapidement. Il faut d'ailleurs comprendre que ces deux choses sont indépendantes pour ODE, notre librairie physique.
Il s'agit des "collisions" et des "corps".

a) Les collisions

Ces dernières peuvent se présenter sous la forme d'une boîte, d'une sphere par exemple ou bien d'un regroupement de Meshs. Dans l'espace de nom d'ODE, il s'agit des Geoms. Nous nous servirons donc de ODE.Geoms.Box et de ODE.Geoms.Sphere pour notre scène.

b) Les corps

Les corps sont plus complexes ; ils ont la charge de représenter toutes les propriétés physiques de nos objets dynamiques. (Nos cubes et notre balle dans le cas présent)

c) La création de notre physique - collisions & corps en action !

Dans la partie précédente nous avons créé nos cubes 3D à l'aide d'Irrlicht, nous devons donc créer maintenant les collisions & corps correspondants à ces cubes !

//81 cubes
int oNbsCube=0;
for (float y=0.0f;y<=40.0f;y+=5.0f)
{
  for(float x=-40f+y;x<=40f-y;x+=5f)
  {
  oBody[oNbsCube] = new Body(oWorld);
  oBody[oNbsCube].Mass = Mass.BoxTotal(5f,5,5,5);
  oBody[oNbsCube].Position = new Vector3(x,y+2.5f,0);
  oBody[oNbsCube].AutoDisable=true;
					
  oGeomBox[oNbsCube] = new Box(5,5,5);
  oGeomBox[oNbsCube].RigidBody = oBody[oNbsCube];
  oSpace.Add(oGeomBox[oNbsCube]);
  oBody[oNbsCube].Enabled=false;
  oNbsCube++;
  }
}

d) La boucle de rendu de la physique

Il faut se poser ici les bonnes questions ; A quelle fréquence re calculer la physique ? Comment faire pour que la vitesse de jeu soit équivalente sur n'importe quel pc ?

Il n'y a pas qu'une unique et bonne façon de faire mais cela étant nous pouvons comprendre facilement que rien n'oblige à aligner la fréquence du rendu graphique avec celui de la physique. Rappelons nous que l'illusion du mouvement se produit à partir de 25 images/secondes. D'un autre côté avec une boucle rapide, la physique et les collisions seront de qualité. Il s'agit donc de tester et de choisir le meilleur compromis.

Voici notre boucle de rendu physique :
while (1 == 1)
{
  Stopwatch stopWatch = Stopwatch.StartNew();	
		
  oSpace.Collide();			
				
  oWorld.QuickStep(0.10f,10);

  oCollider.ClearContactJoints();

  if ( (vitesseBoucle - stopWatch.ElapsedMilliseconds) > 0)
  {
    try
    {
    System.Threading.Thread.Sleep((vitesseBoucle - Convert.ToInt16(stopWatch.ElapsedMilliseconds)));
    }
    catch  {}
  }

 }

Il faut comprendre à partir de ce code qu'ODE "déroule" les calculs liés à la physique étape par étape. Cela se produit avec la méthode : oWorld.QuickStep(0.10f,10);

Etant donné que nous souhaitons dérouler ces étapes de manière universelle (quelque soit le pc qui exécutera cette boucle) nous veillons à la régularité de la boucle qui s'exécutera ainsi à la fréquence précisée par la variable vitesseBoucle.

III) Conclusions et remerciements

Pour aller plus loin, il apparaitrait utile de se fabriquer une classe qui "encapsulerait" à la fois le mesh 3D d'Irrlicht, la géométrie de collision et les corps d'ODE. Avis aux codeurs intéressés ;-)

Un grand merci à Copland pour ce travail d'équipe qui nous permet de vous proposer ici ce petit tutorial qui je l'espère vous servira pour vos réalisations personnelles.

Le source du projet : cliquer ici !
Création du message 08-10-2006 20:39:32 kedu
Ce tuto s'adresse aux débutants avant tout ; le but étant de montrer une manière d'intégrer la physique avec votre moteur graphique favori !
Vous trouverez à la fin l'ensemble du code source en rapport avec cette petite scène. Les dll d'ODE et D'Irrlicht s'y trouvent volontairement au cas où vous ayez besoin de les remettre en réfèrences du projet.


L'objectif de ce tutorial est de mettre au point une petite scène constituée d'un sol, d'un mur de brique et d'une balle ! Un bouton permettra d'appliquer une force à la balle afin que cette dernière percute le mur de brique. Tout un programme !



I) La partie graphique

Rien de difficile ici, nous faisons juste appel au passage à une fenêtre qui nous permet de recueillir les souhaits pour le paramétrage du driver d'Irrlicht. (choix de la résolution, du type de driver, etc.)

Je vous laisse vous reporter au contenu de cette "SetupDriverDialog" qui est on ne peut plus basique.

//Initialisation du driver video
SetupDriverDialog DriverDialog = new SetupDriverDialog();
DriverDialog.ShowDialog();

Voyons maintenant quelque chose de plus intéressant : nous avons initialisé la 3D, il serait peut être temps de penser à la physique !

//Initialisation et lancement de la physique
maPhysique = new Physique();
monThreadDeRenduPhysique = new Thread(new ThreadStart (maPhysique.PhysiqueRenderLoop));
monThreadDeRenduPhysique.Start();

Nous détaillerons dans la partie suivante cette classe qui gère notre physique. Néanmoins on voit ici que l'exécution de cette physique se fait dans un thread à part.

Voici les raisons qui expliquent ce choix :
  • Nous évitons ici de calculer la physique dans notre boucle de rendu 3D d'Irrlicht. Cela n'est pas innocent ; ainsi une mauvaise performance dans le rendu 3D n'influera pas dans le calcul de notre physique. (et l'inverse est aussi vrai)
  • Une autre raison réside dans le fait que nous devons bénéficier d'une "unité de temps" pour notre scène. (vous trouverez l'explication à cela dans la seconde partie)


Pour clore cette première partie, il nous reste à peupler notre scene d'un sol, d'un mur de cubes, d'une balle. A titre d'exemple voici le code de notre mur de cubes :
int NbsCubeSceneNode=0;
for (float y=0.0f;y<=40.0f;y+=5.0f)
{
  for(float x=-40f+y;x<=40f-y;x+=5f)
  {
  CubeSceneNode[NbsCubeSceneNode] = device.SceneManager.AddCubeSceneNode(5,null,-1,new Vector3D(x,y+2.5f,0));
  CubeSceneNode[NbsCubeSceneNode].SetMaterialTexture(0, device.VideoDriver.GetTexture("cube.jpg"));CubeSceneNode[NbsCubeSceneNode].SetMaterialFlag(MaterialFlag.LIGHTING, false);
  NbsCubeSceneNode++;
  }
}

Rien de bien compliqué, il suffit juste d'apprécier la magie d'Irrlicht...

II) La physique

C'est bien entendu ici que réside la difficulté... Par où commencer ? Et bien nous avons deux choses à mettre en place rapidement. Il faut d'ailleurs comprendre que ces deux choses sont indépendantes pour ODE, notre librairie physique.
Il s'agit des "collisions" et des "corps".

a) Les collisions

Ces dernières peuvent se présenter sous la forme d'une boîte, d'une sphere par exemple ou bien d'un regroupement de Meshs. Dans l'espace de nom d'ODE, il s'agit des Geoms. Nous nous servirons donc de ODE.Geoms.Box et de ODE.Geoms.Sphere pour notre scène.

b) Les corps

Les corps sont plus complexes ; ils ont la charge de représenter toutes les propriétés physiques de nos objets dynamiques. (Nos cubes et notre balle dans le cas présent)

c) La création de notre physique - collisions & corps en action !

Dans la partie précédente nous avons créé nos cubes 3D à l'aide d'Irrlicht, nous devons donc créer maintenant les collisions & corps correspondants à ces cubes !

//81 cubes
int oNbsCube=0;
for (float y=0.0f;y<=40.0f;y+=5.0f)
{
  for(float x=-40f+y;x<=40f-y;x+=5f)
  {
  oBody[oNbsCube] = new Body(oWorld);
  oBody[oNbsCube].Mass = Mass.BoxTotal(5f,5,5,5);
  oBody[oNbsCube].Position = new Vector3(x,y+2.5f,0);
  oBody[oNbsCube].AutoDisable=true;
					
  oGeomBox[oNbsCube] = new Box(5,5,5);
  oGeomBox[oNbsCube].RigidBody = oBody[oNbsCube];
  oSpace.Add(oGeomBox[oNbsCube]);
  oBody[oNbsCube].Enabled=false;
  oNbsCube++;
  }
}

d) La boucle de rendu de la physique

Il faut se poser ici les bonnes questions ; A quelle fréquence re calculer la physique ? Comment faire pour que la vitesse de jeu soit équivalente sur n'importe quel pc ?

Il n'y a pas qu'une unique et bonne façon de faire mais cela étant nous pouvons comprendre facilement que rien n'oblige à aligner la fréquence du rendu graphique avec celui de la physique. Rappelons nous que l'illusion du mouvement se produit à partir de 25 images/secondes. D'un autre côté avec une boucle rapide, la physique et les collisions seront de qualité. Il s'agit donc de tester et de choisir le meilleur compromis.

Voici notre boucle de rendu physique :
while (1 == 1)
{
  Stopwatch stopWatch = Stopwatch.StartNew();	
		
  oSpace.Collide();			
				
  oWorld.QuickStep(0.10f,10);

  oCollider.ClearContactJoints();

  if ( (vitesseBoucle - stopWatch.ElapsedMilliseconds) > 0)
  {
    try
    {
    System.Threading.Thread.Sleep((vitesseBoucle - Convert.ToInt16(stopWatch.ElapsedMilliseconds)));
    }
    catch  {}
  }

 }

Il faut comprendre à partir de ce code qu'ODE "déroule" les calculs liés à la physique étape par étape. Cela se produit avec la méthode : oWorld.QuickStep(0.10f,10);

Etant donné que nous souhaitons dérouler ces étapes de manière universelle (quelque soit le pc qui exécutera cette boucle) nous veillons à la régularité de la boucle qui s'exécutera ainsi à la fréquence précisée par la variable vitesseBoucle.

III) Conclusions et remerciements

Pour aller plus loin, il apparaitrait utile de se fabriquer une classe qui "encapsulerait" à la fois le mesh 3D d'Irrlicht, la géométrie de collision et les corps d'ODE. Avis aux codeurs intéressés ;-)

Un grand merci à Copland pour ce travail d'équipe qui nous permet de vous proposer ici ce petit tutorial qui je l'espère vous servira pour vos réalisations personnelles.

Le source du projet : cliquer ici !

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
167 invités en ligne
membre en ligne: -
RSS Feed