Historique des modifications - Message

Message #9004

Sujet: Moteur phisique oui mais le quel ?


Type Date Auteur Contenu
Création du message 21-11-2010 10:04:49 Gehogor
"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();          // Création du monde de Newton

    float min[3];
    float max[3];
    min[0] = -50.0;     // -x dans le vrai monde
    min[1] = -2.0;      // -z dans le vrai monde
    min[2] = -50.0;     // -y dans le vrai monde
    max[0] = 50.0;      // x dans le vrai monde
    max[1] = 50.0;      // z dans le vrai monde
    max[2] = 50.0;      // y dans le vrai monde
    NewtonSetWorldSize(m_nWorld, min, max );

    int materialID = NewtonMaterialGetDefaultGroupID(m_nWorld);     // Récupération de la matière par défaut du monde "Newton"
    NewtonMaterialSetDefaultFriction(m_nWorld, materialID, materialID, 0.8f, 0.4f);         // Configuration de la friction de la matière par défaut
    NewtonMaterialSetDefaultElasticity(m_nWorld, materialID, materialID, 0.8f);             // Configuration de l'élasticité de la matière par défaut
    NewtonMaterialSetDefaultSoftness(m_nWorld, materialID, materialID, 0.05f);              // Configuration de la douceur de la matière par défaut
    NewtonMaterialSetSurfaceThickness(m_nWorld, materialID, materialID,0.0f);               // Ici, je ne sais pas trop... A voir !

    // Association d'une méthode type "Callback" (ici: "ContactsProcess") à la matière par défaut, cette méthode est appellée par le moteur Newton
    // lorsqu'il y a une collision entre de objet possédant cette même matière.
    NewtonMaterialSetCollisionCallback(m_nWorld, materialID, materialID, NULL, OnAABBOverlap, ContactsProcess);

    m_physicsActive = true;         // Permission du thread de tourné
    start();                        // Lancement du thread
}

Transformation d'un objet "physics3D" en objet "Newton":

Code c++ :

QString GrNewton::p_loadPhysics3D(GrPhysics3D* physics3D)
{
    if(physics3D->collisionType() == GrPhysics3D::NO_COLLISION)     // Si l'objet "physics3D" autorise les collisions
        return QObject::trUtf8("Objet [%1] -- partie physique [%2]: Mode de collision désactivé.\
").arg(physics3D->root()->name()).arg(physics3D->name());

    QString tmpInfo = QObject::trUtf8("Objet [%1] -- partie physique [%2]: Mise à jour de la partie physique.\
").arg(physics3D->root()->name()).arg(physics3D->name());

    NewtonCollision* listCollision[NB_MAX_PRIMITIVE];               // Déclaration d'un tableau de pointeur d'objet collision Newton

    int materialID = NewtonMaterialGetDefaultGroupID(m_nWorld);     // Récupération de l'identifiant de la matière par défaut du monde de Newton

    QString material = physics3D->parameter("Material").toString(); // Récupération de l'identifiant de la matière de l'objet "physics3d" concerné
    if(!material.isEmpty())
        materialID = m_physicsMaterial->materialID(material);       // On note le bon identifiant

    int nbForm = 0;

    for(int i=0;i<physics3D->childSize();i++)                       // Parcours de tous les enfants de l'objet "physics3D" pour les transformer en "forme primitive"
    {
        GrPrimitive3D* primitive3D = dynamic_cast<GrPrimitive3D*>(physics3D->child(i));

        if(primitive3D != NULL)
            tmpInfo += p_loadPrimitive3DRecursif(primitive3D,listCollision,materialID,nbForm);  // Méthode de tranformtion ou "mini wrapper"
    }

    if(nbForm == 0)
        return tmpInfo + QObject::trUtf8("Aucune forme primitive de créée.\
");
    else
        tmpInfo += QObject::trUtf8("Nombre total de primitives: %1.\
").arg(nbForm);

    NewtonCollision* newColGroup = NewtonCreateCompoundCollision(m_nWorld,nbForm,listCollision,materialID);     // Fusion des primitives de collision en une seule, maillage purement convex
    NewtonBody* newBody = NewtonCreateBody(m_nWorld,newColGroup);       // Création d'un "NewtonBody"           // Création du corps Newton associé à son maillage de collision

    //---------------------------------- Récupération du maillage --------------------------------// Partie en developpement, peut être non fonctionnel dans Newton 2.0 ?? Car buger ??
    NewtonMesh* nMesh = NewtonMeshCreateFromCollision(newColGroup);

    int faceCount = NewtonMeshGetTotalFaceCount(nMesh);
    int indexCount = NewtonMeshGetTotalIndexCount(nMesh);

    tmpInfo += QObject::trUtf8("Nombre total de face: %1 et d'index %2.\
").arg(faceCount).arg(indexCount);
    /*int vertexStrideInByte,normalStrideInByte,uvStrideInByte0,uvStrideInByte1;    // TODO_G: PAS FONCTIONNEL DANS NEWTON OU AUTRE CHOSE, A VOIR!
    dFloat *vertex,*normal,*uv0,*uv1;

    NewtonMeshGetVertexStreams(nMesh,vertexStrideInByte,vertex,normalStrideInByte,normal,uvStrideInByte0,uv0,uvStrideInByte1,uv1);
    for(int i=0;i<vertexStrideInByte;i=i+3)
    {
        vertex[i];
        vertex[i+1];
        vertex[i+2];
    }*/
    NewtonMeshDestroy(nMesh);
    //--------------------------------------------------------------------------------------------//

    float mPos[16];
    MMatrixToNewtonMatrix(mPos,physics3D->absolutePosition());  // Récupération du la position absolue de notre objet "physics3D"
    NewtonBodySetMatrix(newBody,mPos);                          // On transmet cette position au corps rigide pour newton
    NewtonBodySetMaterialGroupID(newBody,materialID);           // On indique à Newton de quelle matière il est fait
    NewtonBodySetUserData(newBody,physics3D);                   // Stockage de "GrPhysics3D*" pour son utilisation dans les méthode "CallBack"
    physics3D->setUserData(0,reinterpret_cast<void*>(newBody)); // Stockage de "NewtonBody*" afin de pouvoir le réutiliser dans le "run()"

    float inertia[3],origin[3];
    if(physics3D->parameter("AutoInertialAndMass").toBool())    // Calcul automatique de l'inertie de Newton en fonction des formes de collisions
    {
        NewtonConvexCollisionCalculateInertialMatrix(newColGroup,inertia,origin);

        physics3D->setParameter("Ix",inertia[0]);           // On indique à l'objet "physics3D" son inertie
        physics3D->setParameter("Iy",inertia[2]);
        physics3D->setParameter("Iz",inertia[1]);

        physics3D->setParameter("CenterMass_X",origin[0]);  // On indique à l'objet "physics3D" son centre de masse
        physics3D->setParameter("CenterMass_Y",origin[2]);
        physics3D->setParameter("CenterMass_Z",origin[1]);
    }

    float mass = physics3D->parameter("Mass").toFloat();
    NewtonBodySetMassMatrix(newBody,mass,                   // Configuration de la masse et inertie de notre objet Newton
                                    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);              // Configuration du centre de masse et inertie de notre objet Newton

    NewtonBodySetLinearDamping(newBody,physics3D->parameter("LinearDamping").toFloat()); // Configuration de l'amortissement linéaire de notre objet Newton

    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);    // Configuration de l'amortissement rotoïde de notre objet Newton

    NewtonBodySetFreezeState(newBody,0);
    NewtonBodySetAutoSleep(newBody,0);

    // Association d'une "Callback" (ici:SetMeshTransformMesh) à l'objet Newton,
    // elle sera appellée lorsque l'objet bougera selon le moteur Newton (il y a bcp d'exemple là dessus)
    NewtonBodySetTransformCallback(newBody,SetMeshTransformMesh);

    // Association d'une "Callback" (ici:ApplyForceAndTorqueEvent) à l'objet Newton,
    // elle sera appellée lorsque l'objet devra subir une force (il y a bcp d'exemple là dessus)
    NewtonBodySetForceAndTorqueCallback(newBody,ApplyForceAndTorqueEvent);

    float pt0[3],pt1[3];
    NewtonBodyGetAABB(newBody,pt0,pt1);             // Calcul de l'enveloppe totale de l'objet Newton pour information
    tmpInfo += QObject::trUtf8("Dimensions externes: %1 %2 %3.\
").arg(pt1[0]-pt0[0]).arg(pt1[1]-pt0[1]).arg(pt1[2]-pt0[2]);

    for(int i=0;i<nbForm;i++)                       // Désallocation de la mémoire des primitives de collision
       NewtonReleaseCollision(m_nWorld,listCollision[i]);

    NewtonReleaseCollision(m_nWorld,newColGroup);   // Désallocation de la mémoire de la primitive groupe de collision

    return tmpInfo;                                 // On retourne les informations de la méthodes
}

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("ScaleX").toFloat();
    float paramB = primitive3D->parameter("ScaleY").toFloat();
    float paramC = primitive3D->parameter("ScaleZ").toFloat();

    // On récupère la position de la forme primitive du volume de collision par rapport à l'objet lui-même
    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("La primitive est de forme SPHERE.");
        break;

        case GrPrimitive3D::BOX:
            newCol = NewtonCreateBox(m_nWorld,paramA,paramC,paramB,materialID,mPos);
            tmpInfo = QObject::trUtf8("La primitive est de forme BOX.");
        break;

        case GrPrimitive3D::CAPSULE:
            newCol = NewtonCreateCapsule(m_nWorld,paramA/2.0,paramB*2.0,materialID,mPos);
            tmpInfo = QObject::trUtf8("La primitive est de forme CAPSULE.");
        break;

        case GrPrimitive3D::CYLINDER:
            newCol = NewtonCreateCylinder(m_nWorld,paramA/2.0,paramB,materialID,mPos);
            tmpInfo = QObject::trUtf8("La primitive est de forme CYLINDER.");
        break;

        case GrPrimitive3D::CONE:
            newCol = NewtonCreateCone(m_nWorld,paramA/2.0,paramB,materialID,mPos);
            tmpInfo = QObject::trUtf8("La primitive est de forme CONE.");
        break;

        case GrPrimitive3D::CHAMFER_CYLINDER:
            newCol = NewtonCreateChamferCylinder(m_nWorld,paramA/2.0,paramB,materialID,mPos);
            tmpInfo = QObject::trUtf8("La primitive est de forme CHAMFER_CYLINDER.");
        break;

        case GrPrimitive3D::USER_PRIMITIVE:    
            irr::scene::IMesh* mesh = reinterpret_cast<irr::scene::IMesh*>(primitive3D->userData(3));
            if(mesh != NULL)
            {
                float tolerance = primitive3D->parameter("MeshTolerance").toFloat();
                if(mesh != NULL)
                    newCol = p_createCollisionFromMesh(m_nWorld,mesh,tolerance,paramA,paramB,paramC,materialID,mPos);
            }
            tmpInfo = QObject::trUtf8("La primitive est de forme USER_PRIMITIVE.");
        break;
    }

    for(int i=0;i<primitive3D->childSize();i++)         // Fonction récursive qui rappelle tous les enfant pour récupérer toutes les primitives
    {
        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){           // On limite le nombre de collision primitive total pour "UN" objet Newton
            listCollision[internalCounter] = newCol;
            internalCounter++;}

        tmpInfo += QObject::trUtf8(" Création de la primitive réussie.\
");
    }

    return tmpInfo;
}

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