|
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...
|