#0 

28-01-2010 15:54:21

Hawk
Membre
Lieu: Wissous
Date d'inscription: 08-11-2008
Messages: 91
Site web

Bonjour à tous,

Comme vous le savez peut-être (ou pas), je travaille sur un moteur de RPG 3D basé sur Irrlicht. En ce moment, je me pose beaucoup de question quant au moteur de collisions. C'est un moteur qui se veut assez simple, mais je cherche le meilleur moyen de le réaliser.

Concrètement, de quoi doit-il être capable ?
Dans l'idée que j'en ai, il y a deux parties assez distinctes dans ce moteur : les collisions Objet/Objet et les collisions Objet/Terrain.

Pour la gestion des collisions Objet/Objet, il s'agit des collisions 2 à 2 entre objets qui peuvent interagir ou être en mouvement, typiquement, du héros avec un autre personnage, ou de deux personnages entre eux, ou d'un personnage avec une caisse. Ici, une détection de bounding box est largement suffisante, il s'agit juste de savoir si ces deux objets sont à une distance assez petite pour qu'ils puissent interagir.

Pour la gestion du terrain, là encore, ça reste assez simple, je souhaite juste que les personnages mobiles puissent se déplacer sur le sol, qu'ils montent les pentes pas trop raides, et descendent à la hauteur du sol. Ils ne peuvent bien sûr pas passer à travers les bâtiments (de toute façon, un mur est une pente trop raide). Pour la gestion de l'eau, certains objets peuvent flotter dessus, et les autres ne peuvent pas marcher dessus. Par exemple, le héros ne pourra pas traverser une rivière, mais s'il y a une plateforme sur l'eau qui flotte, alors il pourra marcher dessus pour traverser.

Voilà pour la présentation de ce que j'ai en tête. Maintenant mon problème : est-ce que c'est faisable avec Irrlicht seul, ou bien j'aurais besoin d'une bibliothèque externe ?

D'après mon investigation, j'ai déjà quelques éléments de réponses :
- Irrlicht : Avec un CollisionAnimator, je peux régler le problème de la gestion du terrain de manière simple, mais je ne sais pas si c'est très performant ? De plus, il y a des paramètres qui ne sont pas évidents à régler. Pour ce qui est des collisions Objet/Objet, il n'y a pas de méthode simple comme ça, mais je pense qu'un calcul de distance entre les différents objets peut régler le problème, j'ai déjà un système similaire dans mon moteur qui fonctionne assez bien. Reste le problème des performances, mais avec des solutions de découpage de monde (type octree ou autre), je devrais m'en sortir.
- Les bibliothèques externes : j'ai regardé un peu Newton et ODE (pas encore PhysX), elles ont l'air bien performantes, mais assez usine à gaz pour ce que je souhaite faire. Du coup, j'hésite à me lancer dedans.

Comme ça fait plusieurs semaines que je pense sur la question, je me suis dis que peut-être je pourrais avoir des retours d'expériences de personnes qui ont déjà fait des moteurs de collisions et qui seraient en mesure de me conseiller.

D'avance merci.

Hors ligne


#1 

19-01-2011 15:20:51

Metallizer
Abonné
Lieu: Région Parisienne
Date d'inscription: 07-01-2007
Messages: 100
Site web

Bon ça fait quasiment un an que tu as posté ce message mais je tiens quand même à faire partager mon expérience à ce niveau car je suis exactement dans la même situation.

Au départ, je pensais que tout était prévu dans Irrlicht pour gérer des collisions, après tout, c'est une bibliothèque qui est censée faciliter le développement de jeux 3D. Et en effet, il y a le CollisionResponseAnimator qui permet de faire de la collision Objet/Terrain (ou Mesh de décor). Seulement voila, je la trouve extrêmement limitée, d'ailleurs c'est l'avis de tous sur ce forum.

Puis on m'a conseillé d'implémenter un moteur physique. Je suis parti sur Newton mais je ne suis arrivé à rien de bon avec ce moteur. Un simple cube qui tombe sur un plan et le cube passe au travers (il s'enfonce lentement dedans comme dans du sable mouvant) puis tourne sur lui même hmm

Je suis ensuite passé à Bullet, moteur plus apprécié on dirait, il est aussi plus concluant dans mon cas, le cube tombe et s'arrête bien au sol. Je ne suis pas allé plus loin que ça, le cube rebondit sur le sol en fonction de la hauteur à laquelle il a été lâché.
Ce comportement ne me convient pas, je n'ai pas encore trouvé comment paramétrer mes objets pour que le cube tombe et s'arrête net
sur le sol... J'espère seulement que c'est possible.
Autre problème que j'ai : collision Objet/Décor et là je n'ai toujours pas réussi à faire ce que je voulais, à savoir que le cube monte
la pente quand je le déplace. Au lieu de cela, il fonce droit dedans et passe au travers, comme si c'était resté plat. Autre soucis :
Le cube dévale la pente comme si elle était savonneuse, j'espère trouver un moyen de spécifier un seuil à partir duquel mon cube doit
glisser et à quelle vitesse...

Bref je suis un peu déçu de ces moteurs physiques qu'on nous vente à droite et à gauche et je me pose beaucoup de question sur
comment on peut arriver au résultat souhaité. Pourtant, je ne demande pas la lune mais seulement que mon personnage puisse marcher,
gravir les pentes, les descendre. Rien de plus. Mais visiblement ça à l'air super compliqué de mettre en place un tel système.
A moins qu'on m'en apporte la preuve du contraire, les anciens jeux 3D des années 90 n'utilisaient pas de moteurs physiques, j'aimerais
vraiment trouver un article sur le net qui explique le fonctionnement de collisions simples entre une primitive géométrique et un
mesh aux multiples triangles (et sans maths compliquées qui nécessitent un BAC+5 math spé).

En attendant, j'ai avancé sur d'autres aspects de mon jeu, pour le reste, son code source est disponible et mis à jour régulièrement,
si un jour quelqu'un me met le nez dans mes bêtises avec Bullet, ça me rendra un grand service :

http://www.is06.com/telecharger.php

Dernière modification par Metallizer (19-01-2011 15:21:51)

Hors ligne


#2 

19-01-2011 15:42:24

tmyke
Administrateur
Date d'inscription: 24-03-2008
Messages: 1025

Metallizer :

Bref je suis un peu déçu de ces moteurs physiques qu'on nous vente à droite et à gauche et je me pose beaucoup de question sur
comment on peut arriver au résultat souhaité. Pourtant, je ne demande pas la lune mais seulement que mon personnage puisse marcher,
gravir les pentes, les descendre. Rien de plus. Mais visiblement ça à l'air super compliqué de mettre en place un tel système.


Et oui, cela parait tellement simple que l'on en oublie que ces choses qui semblent basiques n'on rien d'évidente à programmer.
Dans les moteurs physique, c'est ce que l'on appelle les 'Characters', et quand tu vois le code, c'est là que tu prend conscience
du boulot que cela représente (interaction parfaite avec l'environnement d'un personnage).

Metallizer :

A moins qu'on m'en apporte la preuve du contraire, les anciens jeux 3D des années 90 n'utilisaient pas de moteurs physiques, j'aimerais
vraiment trouver un article sur le net qui explique le fonctionnement de collisions simples entre une primitive géométrique et un
mesh aux multiples triangles (et sans maths compliquées qui nécessitent un BAC+5 math spé)


Les anciens jeux offraient bien moins de liberté d'actions, et trichait en grande partie. Ce sont des principes pas forcement évident à aborder,
et la mise en pratique risque de te prendre énormément de temps. Je reste persuadé qu'une partie de la solution est lié à un moteur physique,
au moins tu ne réinventera pas la roue, les routines dont tu a besoin sont déjà dedans, bien faite et optimisées.

Metallizer :

Puis on m'a conseillé d'implémenter un moteur physique. Je suis parti sur Newton mais je ne suis arrivé à rien de bon avec ce moteur. Un simple cube qui tombe sur un plan et le cube passe au travers (il s'enfonce lentement dedans comme dans du sable mouvant) puis tourne sur lui même hmm


Pourtant c'est le plus simple et de loin, à tout point de vue. Je commence à bien le connaitre et si tu as eu des soucis
pour le mettre en oeuvre, il ne devait pas franchement manquer grand chose pour que cela tourne. Je ne peux que te le conseiller de nouveau.
Si tu as besoin de conseil le concernant n'hésite pas à poster, j'essaierais de t'aider bien entendu.


Force et sagesse...

Hors ligne


#3 

19-01-2011 16:33:04

nico
Webmaster
Date d'inscription: 07-08-2009
Messages: 563
Corrections: 9

Metallizer :

Puis on m'a conseillé d'implémenter un moteur physique. Je suis parti sur Newton mais je ne suis arrivé à rien de bon avec ce moteur. Un simple cube qui tombe sur un plan et le cube passe au travers (il s'enfonce lentement dedans comme dans du sable mouvant) puis tourne sur lui même hmm

Je suis ensuite passé à Bullet, moteur plus apprécié on dirait, il est aussi plus concluant dans mon cas, le cube tombe et s'arrête bien au sol. Je ne suis pas allé plus loin que ça, le cube rebondit sur le sol en fonction de la hauteur à laquelle il a été lâché.


j'ai l'impression de m'entendre wink j'ai fait pareil que toi, et en passant sur Bullet j'ai compris mon erreur avec newton, il fallait mettre un sol avec une mass à 0.

Hors ligne


#4 

20-01-2011 00:09:52

Metallizer
Abonné
Lieu: Région Parisienne
Date d'inscription: 07-01-2007
Messages: 100
Site web

Merci Tmyke pour ton intervention, j'avais vu que tu étais très satisfait de Newton, j'ai aussi beaucoup aimé la manière de l'implémenter. Ça m'a demandé quelques heures mais finalement j'étais assez content d'avoir compris le fonctionnement de base. Après, si comme le dit nico mon problème résidait dans une masse à 0, j'aurais peut être trouvé mais bien plus tard que le moment où j'ai opté pour Bullet (je pense que ce choix risque d'être définitif pour plusieurs raisons).

Cela dit de manière générale sur les moteurs physiques, c'est très bien qu'ils proposent toutes ces fonctionnalité et ce réalisme physique (rebonds, inertie etc...) mais souvent, pour des projets amateurs modestes, c'est bien au delà de ce qu'on demande en matière de collisions. Et souvent sur le net, on ne trouve que des tutos ou des documentations qui vantent le côté physique/dynamique mais qui traitent très peu l'aspect uniquement collision comme dans un jeu basique.

Par contre oui maintenant je ne pense pas me mettre à coder ce que je souhaite, ça serait réinventer la roue comme tu le dis et surtout, j'imagine que si j'arrive à un résultat, il risque de ne pas être optimisé du tout alors que j'ai potentiellement une solution à ma portée avec Bullet. J'espère juste que mes recherches sur le net vont m'amener à correctement l'utiliser.

Hors ligne


#5 

20-01-2011 08:47:31

tmyke
Administrateur
Date d'inscription: 24-03-2008
Messages: 1025

Certains moteur physique offre une palette de fonction bas niveau pour gérer les collisions simple, sans avoir à passer par une quelconque simulation.
C'est ce que j'ai apprécié dans Newton justement, il possède pas mal de fonctions 'basic' pour faire de simples tests de collide entre deux éléments.
C'est vraiment super léger, pas besoin d'avoir un niveau en math hors norme, et c'est pas buggé.
A titre de comparaison, j'ai eu beaucoup plus de mal avec Bullet pour cela, que je trouve beaucoup moins à son aise la dessus et surtout bien moins intuitif wink


Force et sagesse...

Hors ligne


#6 

20-01-2011 09:33:03

Metallizer
Abonné
Lieu: Région Parisienne
Date d'inscription: 07-01-2007
Messages: 100
Site web

Moi ça ne me dérange pas de passer d'un moteur à l'autre, j'ai structuré mes classes de manière à pouvoir changer ça assez facilement.
Tu n'aurais pas quelques liens ou tuto qui parle de ces fonctions bas niveau ? L'api du site Newton est un peu faiblarde je trouve... ^^'

Hors ligne


#7 

20-01-2011 09:56:12

tmyke
Administrateur
Date d'inscription: 24-03-2008
Messages: 1025

Non, je n'ai pas de tuto en tête spécifique à la gestion des collisions simple.
Mais avec la doc on peut s'en sortir assez facilement.

Pour résumer, voici la méthode générale.

Il te faut créer tout d'abord les shape des objet dont tu veux tester les collisions, normal, faut
bien que Newton ai un semblant de géométrie en tête.
par exemple, pour un cube cela donne cela:

Code c++ :

NewtonCollision *shapeBox = NewtonCreateBox( World, sizex, sizey, sizez, id, NULL);


maintenant si je veux tester si deux éléments sont en collision, il suffit de faire:

Code c++ :


#define MAXPOINTCOLLIDE 64
static float    contacts[MAXPOINTCOLLIDE*3];
static float    normals[MAXPOINTCOLLIDE*3];
static float    penetration[MAXPOINTCOLLIDE*3];

int res = NewtonCollisionCollide( World, MAXPOINTCOLLIDE, shapeBox1, matrixBox1.pointer(), shapeBox2, matrixBox2.pointer(),
                    contacts,normals,penetration, 0);


voilà c'est tout. Avec les explications de la doc, tu n'auras pas vraiment de soucis pour la mise en oeuvre...

il y a par exemple NewtonCollisionPointDistance et surtout NewtonCollisionRayCast qui se rendent
bien utile aussi pour tous les test de collisions avec nos environements...


Force et sagesse...

Hors ligne


#8 

20-01-2011 10:34:10

Metallizer
Abonné
Lieu: Région Parisienne
Date d'inscription: 07-01-2007
Messages: 100
Site web

Merci pour les quelques conseils, je suis en train de réintégrer Newton pour voir si je peux déjà corriger les problèmes que j'ai soulevé. Les collisions entre formes géométriques simples je les faisait jusqu'à maintenant manuellement, ce n'est pas ce qu'il y a de plus dur, mais bon si Newton est plus optimisé que mes tests, c'est peut être pas plus mal.

NewtonCollisionPointDistance et NewtonCollisionRayCast m'intéressent davantage vu que je vais surement en avoir besoin pour que ma caméra ne rentre pas dans le décor...

Mais sinon c'est un peu un dilemme cette histoire de moteurs, Newton a une licence moins souple que celle de Bullet et, de plus en plus, j'ai une optique open source pour mon projet, je verrai à terme ce que je vais faire mais bon pour le moment ma priorité est de faire fonctionner un moteur physique smile

Merci en tout cas.

Hors ligne


#9 

20-01-2011 10:37:43

tmyke
Administrateur
Date d'inscription: 24-03-2008
Messages: 1025

Pour la licence de Newton, pour résumer elle rejoint celle d'Irrlicht , la seule différence c'est que c'est pas de l'open source.


Force et sagesse...

Hors ligne


#10 

20-01-2011 11:13:53

Metallizer
Abonné
Lieu: Région Parisienne
Date d'inscription: 07-01-2007
Messages: 100
Site web

Bon bah j'ai toujours le même problème, le cube tombe et s'enfonce dans le sol en tournant. Je précise que j'utilise pour le cube une collision de type boite (NewtonCreateBox) et que le sol utilise une collision de type "Tree" (NewtonCreateTreeCollision).

Voici un bout de code pour la création du cube :

Code c++ :


void ModelEntity::setBoxCollision(NewtonWorld* world, f32 mass) {
  if(mainNode) {
    // Récupération des dimensions de la boite englobante
    core::vector3df minBox = mainNode->getBoundingBox().MinEdge;
    core::vector3df maxBox = mainNode->getBoundingBox().MaxEdge;

    core::vector3df size(maxBox - minBox);
    core::vector3df originVector(maxBox + minBox);
    originVector.X = originVector.X * 0.5f;
    originVector.Y = originVector.Y * 0.5f;
    originVector.Z = originVector.Z * 0.5f;

    // Création de la collision de type boite
    NewtonCollision* collision = NewtonCreateBox(world, size.X, size.Y, size.Z, 0, NULL);

    f32 initMatrix[16] = { };

    // Création du body newton
    NewtonBody* body = NewtonCreateBody(world, collision, initMatrix);
    NewtonBodySetUserData(body, mainNode);
    NewtonReleaseCollision(world, collision);

    f32 inertia[3] = { 0, 0, 0 };
    f32 origin[3] = {originVector.X, originVector.Y, originVector.Z};
    core::matrix4 transformMatrix;

    core::quaternion q(mainNode->getRotation().X, mainNode->getRotation().Y, mainNode->getRotation().Z, 1.0f);
    core::vector3df v(mainNode->getPosition().X, mainNode->getPosition().Y, mainNode->getPosition().Z);

    q.getMatrix(transformMatrix, v);

    NewtonBodySetMatrix(body, transformMatrix.pointer());

    NewtonBodySetMassMatrix(body, mass, (mass * inertia[0]), (mass * inertia[1]), (mass * inertia[2]));
    NewtonBodySetCentreOfMass(body, origin);

    // Définition des fonctions callback
    NewtonBodySetForceAndTorqueCallback(body, applyForceAndTorqueCallback);
    NewtonBodySetTransformCallback(body, setTransformCallback);
  }
}



Et les deux fonctions qui créent la TreeCollision pour le décor :

Code c++ :


void ModelEntity::setMeshCollision(NewtonWorld* world) {
  if(mainNode) {
    // Création d'une collision de type Tree à laquelle on ajoutera manuellement les faces (polygones)
    NewtonCollision* treeCollision = NewtonCreateTreeCollision(world, 1);
    NewtonTreeCollisionBeginBuild(treeCollision);

    // On récupère les meshBuffer, à chaque meshBuffer, on ajoute les informations à la collision
    for(u32 i = 0; i < mainMesh->getMeshBufferCount(); i++) {
      scene::IMeshBuffer* mb = mainMesh->getMeshBuffer(i);
      addMeshToTreeCollision(mb->getVertexType(), mb, treeCollision, mainNode->getScale());
    }

    NewtonTreeCollisionEndBuild(treeCollision, 1);

    // Création du Body Newton
    f32 bodyMatrix[4] = { 0.f, 0.f, 0.f, 0.f };
    NewtonBody* treeBody = NewtonCreateBody(world, treeCollision, bodyMatrix);
    NewtonReleaseCollision(world, treeCollision);

    NewtonBodySetUserData(treeBody, mainNode);
  }
}

void ModelEntity::addMeshToTreeCollision(video::E_VERTEX_TYPE vertexType, scene::IMeshBuffer* meshBuffer, NewtonCollision* treeCollision, core::vector3df scale) {
  // Tableau qui peut contenir 3 vertices servant à ajouter une face à la collision
  f32 vArray[9];
  bool skipAddMesh = false;
  video::S3DVertex* vertices;

  // On récupère les vertices du mesh dans un tableau
  switch(vertexType) {
    case video::EVT_STANDARD:
      vertices = (video::S3DVertex*) meshBuffer->getVertices();
    break;
    case video::EVT_2TCOORDS:
      vertices = (video::S3DVertex2TCoords*) meshBuffer->getVertices();
    break;
    case video::EVT_TANGENTS:
      vertices = (video::S3DVertexTangents*) meshBuffer->getVertices();
    break;
    default:
      // Type de vertex inconnu, on ne créé pas la collision
      // TODO : l'indiquer dans un log ou la console
      skipAddMesh = true;
    break;
  }

  if(!skipAddMesh) {
    // On récupère tous les indices du mesh dans un tableau
    u16* indices = meshBuffer->getIndices();

    // Les indices permettent de récupérer un vertex précis dans l'ordre ou il a été créé
    // On récupère les vertices par groupe de 3 pour former une face (polygone)
    for(u32 j = 0; j < meshBuffer->getIndexCount(); j += 3) {
      // On récupère les indices des trois vertices courants
      s32 v1i = indices[j];
      s32 v2i = indices[j + 1];
      s32 v3i = indices[j + 2];

      // On récupère les vertices spécifiés par les indices et on applique à leur Position l'échelle du node
      vArray = {
        (vertices[v1i].Pos * scale.X).X,
        (vertices[v1i].Pos * scale.X).Y,
        (vertices[v1i].Pos * scale.X).Z,
        (vertices[v2i].Pos * scale.Y).X,
        (vertices[v2i].Pos * scale.Y).Y,
        (vertices[v2i].Pos * scale.Y).Z,
        (vertices[v3i].Pos * scale.Z).X,
        (vertices[v3i].Pos * scale.Z).Y,
        (vertices[v3i].Pos * scale.Z).Z
      };

      // On ajoute la face à la collision - params(collision, nombreDeVertices, pointeurVersTableauDeVertices, tailleDuVertexEnOctets, ID de la face)
      NewtonTreeCollisionAddFace(treeCollision, 3, vArray, sizeof(f32) * 3, 1);
    }
  }
}



Alors peut être que le problème vient de l'ajout des faces à la TreeCollision, mais je ne vois pas comment faire autrement en fait...

Et en réponse à Nico, vu dans la doc de Newton :
"When a TreeCollision is assigned to a body the mass of the body is ignored in all dynamics calculations. This makes the body behave as a static body."

Du coup fixer une masse au sol me semble pas vraiment possible...

Dernière modification par Metallizer (20-01-2011 11:17:39)

Hors ligne


#11 

20-01-2011 11:56:13

tmyke
Administrateur
Date d'inscription: 24-03-2008
Messages: 1025

Bon, voici quelques bouts de codes qui te permettront j'espère d'y voir plus clair. (au fait je pensait que tu cherchais des élément pour les collisions, par pour la physique dynamique).

Creation d'un simple cube body:

Code c++ :


IBodySceneNode* CreateCubeBody(scene::ImeshSceneNode *ent, bool dynamique)
{
    core::vector3df sc= ent->getScale();
    sx = ent->getBoundingBox().getExtent().X * sc.X;
    sy = ent->getBoundingBox().getExtent().Y * sc.Y;
    sz = ent->getBoundingBox().getExtent().Z * sc.Z;
    NewtonCollision* collision = NewtonCreateBox(nWorld, sx,sy,sz, 0, NULL);


    body = NewtonCreateBody (nWorld, collision);

    // set the transformation for this rigid body
    ent->updateAbsolutePosition();
   
   
    core::matrix4 irr_mat = ent->getRelativeTransformation();
    NewtonBodySetMatrix (body, irr_mat.pointer());

    // set a destructor for this rigid body
    if(dynamique)
    {
        // set the transform call back function
        NewtonBodySetTransformCallback (body, (NewtonSetTransform) bodyPhysicsSetTransform);
        // set the force and torque call back function
        NewtonBodySetForceAndTorqueCallback (body, (NewtonApplyForceAndTorque)bodyPhysicsApplyForceAndTorque);
        NewtonBodySetMassMatrix(body, mass, 1.0f, 1.0f, 1.0f);
    }

    // pour le moment ce code, a oir sinon celui ci-dessus
    NewtonReleaseCollision (nWorld, collision);

    return body;
}



Creation du shape concave

Code c++ :


//---------------------------------------------------------
NewtonCollision* CreateCollideConcave(scene::ISceneNode *ent, int optimized)
{

    NewtonCollision* collision;

    core::vector3df sc= ent->getScale();
    //
    // create the collision tree geometry
    collision = NewtonCreateTreeCollision(nWorld, 0);

    // prepare to create collision geometry
    NewtonTreeCollisionBeginBuild(collision);


    u32 skippedFaceNumber;
    core::array<core::triangle3df> tri;
   
   
    scene::ImeshSceneNode *node = (scene::ImeshSceneNode*) ent;
    tri = getPolys(node->getMesh(), sc, 1.0e-6f, skippedFaceNumber );

    int ntri=0;
    for(u32 i=0; i<tri.size(); i++)
    {    core::vector3df v1[3];
        v1[0] = tri[i].pointA;
        v1[1] = tri[i].pointB;
        v1[2] = tri[i].pointC;
        NewtonTreeCollisionAddFace(collision, 3, &v1[0].X, sizeof (core::vector3df), 1);
        ntri++;
    }

    NewtonTreeCollisionEndBuild(collision, optimized);


    return collision;
}




definition du body static , à partir du collisionShape concave:

Code c++ :


IBodySceneNode* CreateSceneBody(scene::ImeshSceneNode *ent, NewtonCollision* collision)
{
    NewtonCollision* collision = CreateCollideConcave(ent, 0);

    body = NewtonCreateBody (nWorld, collision);

    // set the transformation for this rigid body
    ent->updateAbsolutePosition();
   
   
    core::matrix4 irr_mat = ent->getRelativeTransformation();
    NewtonBodySetMatrix (body, irr_mat.pointer());

    // pour le moment ce code, a oir sinon celui ci-dessus
    NewtonReleaseCollision (nWorld, collision);

    return body;
}



Voilà, le code à quelque manque en terme de définition, c'est pas super propre et fait à l'arrache, mais le principe est là. Cela fonctionne très bien, y compris avec des level complet genre quake3.
smile


Force et sagesse...

Hors ligne


#12 

20-01-2011 13:13:17

Metallizer
Abonné
Lieu: Région Parisienne
Date d'inscription: 07-01-2007
Messages: 100
Site web

Wow et bien c'est plutôt pas mal, mes tests deviennent meilleurs.
J'ai l'impression que mon code  construisait mal la collision boite en utilisant des fonctions que tu n'utilises pas comme NewtonBodySetCentreOfMass... ^^'

Bref ça devient pas mal, le cube s'arrête au sol (il rebondit un peu), par contre, j'ai défini une fonction qui permet de mettre à jour la matrice du body Newton, appelée à
chaque boucle du jeu :

Code c++ :


void ModelEntity::updateBody() {
  core::matrix4 irrMatrix = mainNode->getRelativeTransformation();
  NewtonBodySetMatrix(mainBody, irrMatrix.pointer());
}



Ça marche dans le sens où le cube gravit la pente mais il glisse encore, si je retente, il a plus de mal à gravir... je vais voir si je trouve des moyens de paramétrer tout ça ^^
En tout cas ça avance !

Dernière modification par Metallizer (20-01-2011 13:28:48)

Hors ligne


#13 

20-01-2011 13:40:13

tmyke
Administrateur
Date d'inscription: 24-03-2008
Messages: 1025

en fait ce sont les callbacks qui sont passés dans les fonctions NewtonBodySetForceAndTorqueCallback et NewtonBodySetTransformCallback
et qui pourraient ressembler à cela:

Code c++ :


// set the transformation of a rigid body
void bodyPhysicsSetTransform(const NewtonBody* body, const dFloat* matrix, int threadIndex)
{
    // get the graphic object form the rigid body
    IBodySceneNode* eBody= (IBodySceneNode*) NewtonBodyGetUserData(body);
    // set the transformation matrix for this rigid body
    core::matrix4 irr_mat;
    memcpy( irr_mat.pointer() , matrix, sizeof(float)*16);

    eBody->body_mesh->setPosition(irr_mat.getTranslation());
    eBody->body_mesh->setRotation(irr_mat.getRotationDegrees());
        // set node rotation
    eBody->body_mesh->updateAbsolutePosition();
}



et

Code c++ :


// add force and torque to rigid body
void  bodyPhysicsApplyForceAndTorque (const NewtonBody* body, dFloat timestep, int threadIndex)
{
    dFloat Ixx;
    dFloat Iyy;
    dFloat Izz;
    dFloat mass;

    NewtonBodyGetMassMatrix (body, &mass, &Ixx, &Iyy, &Izz);
    core::vector3df force(0.0f, -mass * 10.0f, 0.0f);
    //FORCE
    NewtonBodySetForce(body, &total_force.X);
}

Force et sagesse...

Hors ligne


#14 

20-01-2011 14:10:40

Metallizer
Abonné
Lieu: Région Parisienne
Date d'inscription: 07-01-2007
Messages: 100
Site web

Oui ça les callbacks je n'avais aucun soucis là dessus, c'est même logique dans le fonctionnement.
Par contre j'ai plus de mal à faire en sorte que mon cube :
- d'une part reste bien droit (ne se mette pas à faire des rotations dans tous les sens, même lorsqu'il tombe dans une pente
- qu'il ne glisse pas dans la pente
- ait un seuil au delà du quel il ne peut plus gravir les pentes (mur) ou alors avec du mal (pente raide) et fixer aussi des pentes savonneuses au besoin...

D'ailleurs, je me demande quelle primitive il faut mieux utiliser pour un personnage humain, un cube ne me semble pas adapté, j'irai naturellement vers un cylindre plutôt non ?

Hors ligne


#15 

20-01-2011 14:49:12

tmyke
Administrateur
Date d'inscription: 24-03-2008
Messages: 1025

pour mieux contrôler ton cube passe par setmassMatrix, cela devrait apporter une amélioration dans la stabilité durant la chute.

Sinon, une capsule est le plus souvent employé comme shape représentatif d'un personnage. Et si tu veux faire du 'character control', regarde dans le SDK de
Newton, il y a des codes dédié, qui te simplifieront la vie je pense wink


Force et sagesse...

Hors ligne


#16 

20-01-2011 17:34:30

Metallizer
Abonné
Lieu: Région Parisienne
Date d'inscription: 07-01-2007
Messages: 100
Site web

Non, je n'arrive à rien avec NewtonBodySetMassMatrix, le cube glisse toujours le long de ma pente, que je fixe des valeurs nulles, petites, grandes, négatives, asymétriques. Alors, le mouvement est différent à chaque fois mais bon, rien pour désactiver les valeurs d'inertie et de glissade complètement. Après, je pensais regarder un peu du côté des Materials pour voir si il fallait définir une zone sur le sol où le frottement (ou glissade ou quoi que ce soit) soit nul, du coup quand je lâche ma direction, mon cube reste dans la pente sans bouger...
Puis ensuite j'ai regardé l'histoire du CustomPlayerController qu'on peut trouver dans dCustomJoints du sdk. yikes 900 lignes de code, avec sûrement plein de choses qui ne me serviront pas, j'ai essayé de comprendre un peu mais je n'ai déjà pas d'expérience dans l'utilisation des joints de Newton. hmm

Bref plus j'avance et plus j'ai l'impression que ces bibliothèques c'est vraiment trop de choses dont on n'a pas besoin mais qu'on est obligé d'intégrer pour un résultat très approximatif, je comprend que beaucoup se cassent le nez et abandonnent à ce niveau. sad

Hors ligne


#17 

20-01-2011 17:39:26

tmyke
Administrateur
Date d'inscription: 24-03-2008
Messages: 1025

Oui pour les material, il te permette effectivement de changer les différents paramètre de surface et donc les comportements qui vont avec.

Sinon, effectivement, la prise en main d'un moteur physique reste une tâche qui ne s'improvise pas. Cela se travaille.

Profite éventuellement des fonction simple de détection de collisions pour faire un code perso...


Force et sagesse...

Hors ligne


#18 

20-01-2011 17:47:34

Metallizer
Abonné
Lieu: Région Parisienne
Date d'inscription: 07-01-2007
Messages: 100
Site web

Tu as raison, je crois que je devrais laisser tomber la dynamique et plutôt gérer moi même la gravité. Après tout, je ne veux qu'un truc simple : que le cube s'arrête au contact du sol. Je vais essayer de faire quelque chose avec les fonctions dont tu m'as parlé ce matin.

Hors ligne


#19 

20-01-2011 18:03:59

tmyke
Administrateur
Date d'inscription: 24-03-2008
Messages: 1025

Utilise les fonction RayCast pour cela, c'est la base d'ailleurs du CharacterControler wink


Force et sagesse...

Hors ligne


#20 

21-01-2011 14:09:29

Metallizer
Abonné
Lieu: Région Parisienne
Date d'inscription: 07-01-2007
Messages: 100
Site web

Re !

J'ai regardé un peu NewtonCollisionRayCast et NewtonCollisionCollide. Sur cette dernière, j'arrive à avoir une information de collision entre mes deux objets (personnage et sol) et c'est nickel. Par contre, pour le raycast, j'ai un peu de mal à comprendre la logique.
La fonction attend en premier paramètre une collision, mais laquelle ? Celle du personnage (Box) ou celle du sol (Tree) ? Après le p0 je lui affecte la position de ma box, par contre p1 je ne vois pas quoi lui attribuer. la position + la taille de ma box ?

Si tu as quelques explications Tmyke, ça serait vraiment parfait smile

Hors ligne


#21 

21-01-2011 16:39:31

tmyke
Administrateur
Date d'inscription: 24-03-2008
Messages: 1025

c'est beaucoup plus simple que cela, NewtonCollisionRayCast regarde si il y a une collision entre un shape, et un vecteur dont tu fournis les deux extrémités.
exemple de codage:

Code c++ :


    float normals[128];
    int face_id;
    core::vector3df origin(x,y,z);
    core::vector3df end(dx,dy,dz);
    core::matrix4 mat, inv;

    mat = ent->getAbsoluteTransformation();
    mat.getInverse( inv );
        //
    inv.transformVect( origin );
    inv.transformVect( end );

    float val = NewtonCollisionRayCast( collision ,&origin.X, &end.X, normals , &face_id);


val est compris entre 0 et 1 si il y a collision et il représente la distance entre l'origine du vecteur et la collision.

Voilà, en espérant que tu y vois plus clair wink


Force et sagesse...

Hors ligne


#22 

21-01-2011 18:42:29

Metallizer
Abonné
Lieu: Région Parisienne
Date d'inscription: 07-01-2007
Messages: 100
Site web

J'y vois presque clair, j'avais plus ou moins cru comprendre qu'on testais bien un vecteur avec une collision.

Donc il faut que je passe l'objet NewtonCollision de mon décor en premier paramètre. Par contre, je ne vois pas la logique avec les vecteurs.
Tu mets par exemple dx, dy, dz... que représentent ces variable ? Je suppose un delta pour chaque coordonnées mais il correspond à quoi ? A la vitesse ? A la taille de ma primitive à laquelle le vecteur est rattaché ? Moi je n'obtient que 1.2 en résultat de la collision, quel que soit l'emplacement de mon vecteur...

Code c++ :


f32 normals[128];
s32 faceId;

core::vector3df origin(
  mainNode->getPosition().X,
  mainNode->getPosition().Y,
  mainNode->getPosition().Z
);
core::vector3df end(
  mainNode->getPosition().X,
  mainNode->getPosition().Y - 1.0f,
  mainNode->getPosition().Z
);
core::matrix4 mat, inv;

mat = mainNode->getAbsoluteTransformation();
mat.getInverse(inv);
inv.transformVect(origin);
inv.transformVect(end);

f32 ray = NewtonCollisionRayCast(otherBodyCollision, &origin.X, &end.X, normals, &faceId);

Hors ligne


#23 

21-01-2011 18:53:46

tmyke
Administrateur
Date d'inscription: 24-03-2008
Messages: 1025

L'origine du vecteur est lié à l'objet que tu veux tester sur ton décort.

Quand à sa longueur, c'est le paramètre le plus subtile. C'est à toi de voir. Elle peut dépendre de la hauteur que tu souhaite adopter pour ton person.
Par exemple, tant qu'il n'y a pas collision du ray, ton perso descent.

Si val>1.0 (1.2 dans ton cas) c'est qu'il n'y pas de collision détectée...


Force et sagesse...

Hors ligne


#24 

21-01-2011 19:31:05

Metallizer
Abonné
Lieu: Région Parisienne
Date d'inscription: 07-01-2007
Messages: 100
Site web

Bon Tmyke, tu es un génie ! Merci énormément pour tes conseils. J'ai enfin le résultat que je voulais.

Pour décrire un peu (pour les visiteurs qui coincent comme moi), voici un peu ce que j'ai fait pour mon cas :

- J'ai attribué une TreeCollision à mon mesh qui est le décor
  - J'ai ajouté chaque triangle du mesh Irrlicht au TreeCollision selon la méthode qu'on peut trouver un peu partout
- J'ai considéré que l'origine du vecteur était le centre de mon personnage (ici un cube pour le moment)
- La fin du vecteur est le bas du personnage (je retranche 1.0f à la coordonnée Y vu que mon cube fait 2.0f de hauteur)

Et dans ma boucle principale :
Si le résultat du rayCast est supérieur à 1.0f, si oui :
  - Je fait descendre mon cube
Fin Si
Si le résultat du rayCast est inférieur à 1.0f :
  Tant que le résultat du rayCast est inférieur à 0.95f :
    - Je remonte mon cube
  Fin Tant que
Fin Si

Avec cette méthode, mon cube gravit et descend les pentes sans problème.

Je publierai du code sur mon blog dans la section programmation.
Et une nouvelle démo pour vous montrer ça dans la soirée.

Merci encore ! smile

Hors ligne


Options Liens officiels Caractéristiques Statistiques Communauté
Corrections
irrlicht
irrklang
irredit
irrxml
xhtml 1.0
css 2.1
Propulsé par FluxBB
Traduit par FluxBB.fr
882 membres
1429 sujets
11119 messages
Dernier membre inscrit: LiseBuisson96
23 invités en ligne
Aucun membre connecté
RSS Feed