Historique des modifications - Message

Message #9384

Sujet: Système de collisions de type RPG


Type Date Auteur Contenu
Dernière modification 20-01-2011 10:17:39 Metallizer
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...
Création du message 20-01-2011 10:13:53 Metallizer
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...

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