"Re"-effectivement, je partage complètement l'avis de nabouill et Magnum. Cependant je me mets à ta place et je me dis que ce n'est pas évident de faire son wrapper tout seul.
Et bien je te rassure, en fait, ça se fait très bien. J'en ai fait un entre Irrlicht et Newton 2.0 pour toute collision avec tous les paramètres physiques que le moteur physique met à disposition (par contre pas de ragdoll mais l'esprit est très clairement le même, désolé...) et c'est pas mal.
Bon, tout n'est pas fonctionnel dans Newton 2.0, il faut laisser du temps mais ça le fait quand même. Ce n'est pas très bien documenté mais il y a des exemples.
Pour finir, avoir un code qui distingue bien la partie physique de la partie graphique et bien plus propre à mon sens. En cas de gros bug "mystique venant de l'espace" c'est plus facile d'arrêter un des deux moteurs pour le corriger, enfin bon ...
Je ne sais pas si ça peut t'aider, mais ci-dessous je te transmets trois méthodes qui utilisent Newton. Elles transforment un objet "GrPhysics3D" en objet "Newton" ou plutôt "NewtonBody". L'objet "GrPhysics3D" est un objet perso, tu peux utiliser le tien évidemment. Normalement il y a des commentaires pour suivre le déroulement, j'espère que ça pourra t'aider un peu, on ne sais jamais. Les méthodes a priori peuvent faire peur mais en fait non, si tu suis le déroulement, ça devrait le faire, ...
Fonction d'initialisation:
Code c++ :
GrNewton::initialisation()
{
m_nWorld = NewtonCreate();
float min[3];
float max[3];
min[0] = -50.0; min[1] = -2.0; min[2] = -50.0; max[0] = 50.0; max[1] = 50.0; max[2] = 50.0; NewtonSetWorldSize(m_nWorld, min, max );
int materialID = NewtonMaterialGetDefaultGroupID(m_nWorld); NewtonMaterialSetDefaultFriction(m_nWorld, materialID, materialID, 0.8f, 0.4f); NewtonMaterialSetDefaultElasticity(m_nWorld, materialID, materialID, 0.8f); NewtonMaterialSetDefaultSoftness(m_nWorld, materialID, materialID, 0.05f); NewtonMaterialSetSurfaceThickness(m_nWorld, materialID, materialID,0.0f);
NewtonMaterialSetCollisionCallback(m_nWorld, materialID, materialID, NULL, OnAABBOverlap, ContactsProcess);
m_physicsActive = true; start(); }
Transformation d'un objet "physics3D" en objet "Newton":
Code c++ :
QString GrNewton::p_loadPhysics3D(GrPhysics3D* physics3D)
{
if(physics3D->collisionType() == GrPhysics3D::NO_COLLISION) return QObject::trUtf8("Objet [%1] -- partie physique [%2]: Mode de collision désactivé.\n").arg(physics3D->root()->name()).arg(physics3D->name());
QString tmpInfo = QObject::trUtf8("Objet [%1] -- partie physique [%2]: Mise à jour de la partie physique.\n").arg(physics3D->root()->name()).arg(physics3D->name());
NewtonCollision* listCollision[NB_MAX_PRIMITIVE];
int materialID = NewtonMaterialGetDefaultGroupID(m_nWorld);
QString material = physics3D->parameter("Material").toString(); if(!material.isEmpty())
materialID = m_physicsMaterial->materialID(material);
int nbForm = 0;
for(int i=0;i<physics3D->childSize();i++) {
GrPrimitive3D* primitive3D = dynamic_cast<GrPrimitive3D*>(physics3D->child(i));
if(primitive3D != NULL)
tmpInfo += p_loadPrimitive3DRecursif(primitive3D,listCollision,materialID,nbForm); }
if(nbForm == 0)
return tmpInfo + QObject::trUtf8("Aucune forme primitive de créée.\n");
else
tmpInfo += QObject::trUtf8("Nombre total de primitives: %1.\n").arg(nbForm);
NewtonCollision* newColGroup = NewtonCreateCompoundCollision(m_nWorld,nbForm,listCollision,materialID); NewtonBody* newBody = NewtonCreateBody(m_nWorld,newColGroup);
NewtonMesh* nMesh = NewtonMeshCreateFromCollision(newColGroup);
int faceCount = NewtonMeshGetTotalFaceCount(nMesh);
int indexCount = NewtonMeshGetTotalIndexCount(nMesh);
tmpInfo += QObject::trUtf8("Nombre total de face: %1 et d'index %2.\n").arg(faceCount).arg(indexCount);
NewtonMeshDestroy(nMesh);
float mPos[16];
MMatrixToNewtonMatrix(mPos,physics3D->absolutePosition()); NewtonBodySetMatrix(newBody,mPos); NewtonBodySetMaterialGroupID(newBody,materialID); NewtonBodySetUserData(newBody,physics3D); physics3D->setUserData(0,reinterpret_cast<void*>(newBody));
float inertia[3],origin[3];
if(physics3D->parameter("AutoInertialAndMass").toBool()) {
NewtonConvexCollisionCalculateInertialMatrix(newColGroup,inertia,origin);
physics3D->setParameter("Ix",inertia[0]); physics3D->setParameter("Iy",inertia[2]);
physics3D->setParameter("Iz",inertia[1]);
physics3D->setParameter("CenterMass_X",origin[0]); physics3D->setParameter("CenterMass_Y",origin[2]);
physics3D->setParameter("CenterMass_Z",origin[1]);
}
float mass = physics3D->parameter("Mass").toFloat();
NewtonBodySetMassMatrix(newBody,mass, physics3D->parameter("Ix").toFloat()*mass,
physics3D->parameter("Iy").toFloat()*mass,
physics3D->parameter("Iz").toFloat()*mass);
origin[0] = physics3D->parameter("CenterMass_X").toFloat();
origin[2] = physics3D->parameter("CenterMass_Y").toFloat();
origin[1] = physics3D->parameter("CenterMass_Z").toFloat();
NewtonBodySetCentreOfMass(newBody,origin);
NewtonBodySetLinearDamping(newBody,physics3D->parameter("LinearDamping").toFloat());
float angularDamping[3];
angularDamping[0] = physics3D->parameter("AngularDamping_Rx").toFloat();
angularDamping[1] = physics3D->parameter("AngularDamping_Ry").toFloat();
angularDamping[2] = physics3D->parameter("AngularDamping_Rz").toFloat();
NewtonBodySetAngularDamping(newBody,angularDamping);
NewtonBodySetFreezeState(newBody,0);
NewtonBodySetAutoSleep(newBody,0);
NewtonBodySetTransformCallback(newBody,SetMeshTransformMesh);
NewtonBodySetForceAndTorqueCallback(newBody,ApplyForceAndTorqueEvent);
float pt0[3],pt1[3];
NewtonBodyGetAABB(newBody,pt0,pt1); tmpInfo += QObject::trUtf8("Dimensions externes: %1 %2 %3.\n").arg(pt1[0]-pt0[0]).arg(pt1[1]-pt0[1]).arg(pt1[2]-pt0[2]);
for(int i=0;i<nbForm;i++) NewtonReleaseCollision(m_nWorld,listCollision[i]);
NewtonReleaseCollision(m_nWorld,newColGroup);
return tmpInfo; }
Fonction intermédiaire appellée dans "p_loadPhysics3D":
Code c++ :
QString GrNewton
::p_loadPrimitive3DRecursif
(GrPrimitive3D
* primitive3D
,NewtonCollision
* listCollision
[],int materialID
,int& internalCounter
){ QString tmpInfo
; float mPos
[16]; float paramA
= primitive3D
->parameter
("Objet [%1] -- partie physique [%2]: Mode de collision désactivé.\n").toFloat
(); float paramB
= primitive3D
->parameter
("Objet [%1] -- partie physique [%2]: Mise à jour de la partie physique.\n").toFloat
(); float paramC
= primitive3D
->parameter
("Material").toFloat
(); MMatrixToNewtonMatrix
(mPos
,primitive3D
->relativePosition
()); NewtonCollision
* newCol
= NULL
; switch(primitive3D
->primitiveForm
()) { case GrPrimitive3D
::SPHERE
: newCol
= NewtonCreateSphere
(m_nWorld
,paramA
/2.0,paramC
/2.0,paramB
/2.0,materialID
,mPos
); tmpInfo
= QObject
::trUtf8
("Aucune forme primitive de créée.\n"); break; case GrPrimitive3D
::BOX
: newCol
= NewtonCreateBox
(m_nWorld
,paramA
,paramC
,paramB
,materialID
,mPos
); tmpInfo
= QObject
::trUtf8
("Nombre total de primitives: %1.\n"); break; case GrPrimitive3D
::CAPSULE
: newCol
= NewtonCreateCapsule
(m_nWorld
,paramA
/2.0,paramB
*2.0,materialID
,mPos
); tmpInfo
= QObject
::trUtf8
("Nombre total de face: %1 et d'index %2.\n"); break; case GrPrimitive3D
::CYLINDER
: newCol
= NewtonCreateCylinder
(m_nWorld
,paramA
/2.0,paramB
,materialID
,mPos
); tmpInfo
= QObject
::trUtf8
("AutoInertialAndMass"); break; case GrPrimitive3D
::CONE
: newCol
= NewtonCreateCone
(m_nWorld
,paramA
/2.0,paramB
,materialID
,mPos
); tmpInfo
= QObject
::trUtf8
("Ix"); break; case GrPrimitive3D
::CHAMFER_CYLINDER
: newCol
= NewtonCreateChamferCylinder
(m_nWorld
,paramA
/2.0,paramB
,materialID
,mPos
); tmpInfo
= QObject
::trUtf8
("Iy"); break; case GrPrimitive3D
::USER_PRIMITIVE
: irr::scene::IMesh* mesh
= reinterpret_cast
<irr::scene::IMesh*>(primitive3D
->userData
(3)); if(mesh
!= NULL
) { float tolerance
= primitive3D
->parameter
("Iz").toFloat
(); if(mesh
!= NULL
) newCol
= p_createCollisionFromMesh
(m_nWorld
,mesh
,tolerance
,paramA
,paramB
,paramC
,materialID
,mPos
); } tmpInfo
= QObject
::trUtf8
("CenterMass_X"); break; } for(int i
=0;i
<primitive3D
->childSize
();i
++) { GrPrimitive3D
* child
= dynamic_cast
<GrPrimitive3D
*>(primitive3D
->child
(i
)); if(child
!= NULL
) tmpInfo
+= p_loadPrimitive3DRecursif
(child
,listCollision
,materialID
,internalCounter
); } if(newCol
!= NULL
){ if(internalCounter
<NB_MAX_PRIMITIVE
){ listCollision
[internalCounter
] = newCol
; internalCounter
++;} tmpInfo
+= QObject
::trUtf8
("CenterMass_Y"); } return tmpInfo
;}