#1 

29-07-2010 15:53:23

mr.xyz
Membres
Date d'inscription:
Messages: 15
IP: 86.221.78.151
Courriel

Bonjour,
voila, pour incliner un mesh (ici une fourmi) qui évolue sur un terrain, j'utilise les triangles selectors en créant une ligne au dessus du mesh et en récupérant le triangle de la collision avec cette ligne, je récupère sa normale. Mais voila, mon mesh s'incline n'importe comment, je ne sais plus quoi faire... Merci d'avance wink

voici le code :

Code c++ :


    while (device->run())
    {
        driver->beginScene(true,true,0);

        // Mouvement du model
        mManager.moveObjects();

        // Remise à jour de la position du modèle
        modelPosition = Nmodel->getPosition();

        verticalLine.start = modelPosition;
        verticalLine.end = modelPosition;

        verticalLine.start.Y += 1000;
        verticalLine.end.Y -= 1000;

        selectedSceneNode =
            collMan->getSceneNodeAndCollisionPointFromRay(
                verticalLine,
                intersection,
                hitTriangle,
                IDFlag_IsPickable, // This ensures that only nodes that we have set up to be pickable are considered
                0); // Check the entire scene (this is actually the implicit default)

        if(selectedSceneNode != 0)
        {
                core::vector3df normal = hitTriangle.getNormal().normalize();
                core::vector3df newModelRotation = Nmodel->getRotation();

                // Inclinaison en X
                newModelRotation.X = acos(normal.X) * 180.0 / PI;

                // Inclinaison en Z
                newModelRotation.Z = acos(normal.Z) * 180.0 / PI;

                Nmodel->setRotation(newModelRotation);
        }

        // Affichage
        sceneManager->drawAll();

        driver->endScene();
    }


Hors ligne


#2 

29-07-2010 19:52:48

firnafin
Membres
Avatar de firnafin
Date d'inscription:
Messages: 150
IP: 93.9.158.159
Courriel

ca vient de

Code c++ :

                newModelRotation.X = acos(normal.X) * 180.0 / PI;

                // Inclinaison en Z
                newModelRotation.Z = acos(normal.Z) * 180.0 / PI;

acos c'est arscosinus et pour obtenir un angle il faut donnée le rapport de deux longueurs , faire un petit tour sur des cours de trigonometrie peut etre .Ou bien utiliser des fonctions toutes faites regarde dans la doc de irr::core::vector3d , il y a des methodes pour recupérer des angles à partir d'un vecteur : getHorizontalAngle ,getSphericalCoordinateAngles , devrait faire l'affaire si je ne m'abuse.


Hors ligne


#3 

29-07-2010 22:32:10

mr.xyz
Membres
Date d'inscription:
Messages: 15
IP: 86.221.78.151
Courriel

Si je veux l'inclinaison en X du terrain pour le mesh, il faut bien que je fasse le produit scalaire de la normal au terrian (normalisée) et de l'axe X(1,0,0) ? Ce produit scalaire renvoi le cosinus de l'angle donc je pensait qu'avec arc cosinus je retrouvais l'angle..


Hors ligne


#4 

30-07-2010 09:59:50

firnafin
Membres
Avatar de firnafin
Date d'inscription:
Messages: 150
IP: 93.9.158.159
Courriel

le produit scalaire entre le vecteur normale est l'axe X ne donne pas le cos de l'angle X, mais le cos de l'angle entre les 2 vecteurs.Si tu veux le faire ac la trigo sans passer par les methodes que j'ai citées , tu peux faire comme ca :

Angle_X=atan2(Normale_Z,Normale_Y)*RADTODEG;
Angle_Z=-atan2(Normale_X,Normale_Y)*RADTODEG;
Node->setRotatio(vector3df(Angle_X,0,Angle_Z));

( le moins vient du fait que les rotations d' irrlicht tourne dans le sens anti-trigo selon Z , rotation de l'axe X vers l'axe Y )

Et la ca devrait marcher.


Hors ligne


#5 

30-07-2010 12:38:45

mr.xyz
Membres
Date d'inscription:
Messages: 15
IP: 86.221.78.151
Courriel

euh sa ne marche pas, les deux angles restent entre 0,0 et 0,1 sad

le code:

Code c++ :


                core::vector3df normal = hitTriangle.getNormal().normalize();
                core::vector3df newModelRotation = Nmodel->getRotation();

                newModelRotation.X = atan2(normal.Z,normal.Y);

                cout<<"angle X: "<<newModelRotation.X<<endl;

                newModelRotation.Z = -atan2(normal.X,normal.Y);

                cout<<"angle Z: "<<newModelRotation.Z<<endl;

                Nmodel->setRotation(newModelRotation);


Hors ligne


#6 

30-07-2010 12:48:49

mr.xyz
Membres
Date d'inscription:
Messages: 15
IP: 86.221.78.151
Courriel

firnafin Ecris:

le produit scalaire entre le vecteur normale est l'axe X ne donne pas le cos de l'angle X, mais le cos de l'angle entre les 2 vecteurs.

Je sais bien c'est pour ca, je sais que le produit scalaire renvoi l'angle entre deux vecteurs, je voulais obtenir l'angle entre l'axe X et la normale du terrain (normalisée). Mais faire le produit scalaire avec (1,0,0) sa revient a garder juste la coordonnée X (en tant que cosinus du coup, c'est bizarre en effet mais logique non ?) . Ensuite bah avec acos je retrouvais l'angle (je commence a douter si c'est bien l'angle que je recherche...)


Hors ligne


#7 

30-07-2010 13:04:08

firnafin
Membres
Avatar de firnafin
Date d'inscription:
Messages: 150
IP: 93.9.158.159
Courriel

comme je l'ai deja dit ce n'est pas la meme chose ; exemple : normale_x= < (1,1,1) , (1,0,0) > = 1 , acos(1)=0 de meme selon Z et Y on trouve 3 angles de 0 .... impossible.
Ce que je t'ai donné marche parfaitement il me semble. Deja tu as oublié de multiplier les arc-tangent par irr::core::RADTODEG. De plus tu gardes la rotation selon Y ce qui fait tout planter ( tu rajoute une rotation , alors que les 2 angles fournis suffisent à avoir l'alignement de la direction Y du node avec le vecteur normal ).


Hors ligne


#8 

30-07-2010 13:44:23

mr.xyz
Membres
Date d'inscription:
Messages: 15
IP: 86.221.78.151
Courriel

Ah oui j'avai oublié le radtodeg, sa a l'air de marcher maintenant, par contre je ne comprends pas pourquoi la rotation en Y ferait tout planter, il faut bien que mon mesh tourne quand même smile


Hors ligne


#9 

30-07-2010 13:57:19

firnafin
Membres
Avatar de firnafin
Date d'inscription:
Messages: 150
IP: 93.9.158.159
Courriel

setRotation définie une rotation dans le repere parent. Par exemple supposons que la normale soit (1,1,1) et que tu ais fait la rotation selon X et Z comme ci dessu ,si tu rajoutes une composante selon Y de 45 alors le vecteur (0,1,0) de ton perso va se retrouvée en (0,quelque chose,quelque chose) ce qui est différent de (1,1,1). ce qu'il faut faire c'est faire tourner la node dans son repere selon Y. Pour ce faire tu récupères la matrice de la node par m=node->getTransformation() puis tu recupére l'axe Y perso_y=m.rotateVect(0,1,0) puis node->setRotation(angle_souhaité*perso_y)


Hors ligne


#10 

05-08-2010 14:10:56

mr.xyz
Membres
Date d'inscription:
Messages: 15
IP: 87.90.98.127
Courriel

firnafin Ecris:

setRotation définie une rotation dans le repere parent. Par exemple supposons que la normale soit (1,1,1) et que tu ais fait la rotation selon X et Z comme ci dessu ,si tu rajoutes une composante selon Y de 45 alors le vecteur (0,1,0) de ton perso va se retrouvée en (0,quelque chose,quelque chose) ce qui est différent de (1,1,1).

Je ne comprends pas trop ce que tu veux dire :p :

  • le repère parent standard c'est bien le repère général, celui de la scène? (simple question ^^)
  • de quelle normale parles tu, celle du terrain ou du mesh ?
  • une composante Y de 45 => tu veux dire une rotation de 45 ° pour tourner le personnage ?


firnafin Ecris:

ce qu'il faut faire c'est faire tourner la node dans son repere selon Y. Pour ce faire tu récupères la matrice de la node par m=node->getTransformation() puis tu recupére l'axe Y perso_y=m.rotateVect(0,1,0) puis node->setRotation(angle_souhaité*perso_y)

  • l'angle souhaité est le vecteur de rotation, avec Y à 0 comme tu disais ?
  • rotateVect est de type void, je pense donc que tu voulais dire de créer un vector (0,1,0) et de le passer en passer en référence ?
  • ensuite setRotation prends en paramètre un vecteur, donc je ne comprends pas "angle_souhaité*perso_y"


Merci d'avance wink


Hors ligne


#11 

05-08-2010 22:13:11

firnafin
Membres
Avatar de firnafin
Date d'inscription:
Messages: 150
IP: 93.9.158.30
Courriel

mr.xyz Ecris:

  • le repère parent standard c'est bien le repère général, celui de la scène? (simple question ^^)

pas toujours, tu peux affilier une node a une autre node ( du coup le parent n'est pas le repère general )

exemple : la tourelle d'un char avec pour parent le char, ainsi setRotation(irr::core::vector3df(0,1,0)) va faire tourner la tourelle comme il faut meme si le char admet lui aussi des rotations dû au terrain par exemple, si la tourelle n'est pas fils de char setRotation(irr::core::vector3df(0,1,0)) va faire n'importe quoi .

le parent par defaut est "root" ( cf irr::scene::scenemanager::getRoot ) qui fournie le repère general.

mr.xyz Ecris:

  • de quelle normale parles tu, celle du terrain ou du mesh ?

celle du terrain.

mr.xyz Ecris:

  • une composante Y de 45 => tu veux dire une rotation de 45 ° pour tourner le personnage ?

oui

mr.xyz Ecris:

  • l'angle souhaité est le vecteur de rotation, avec Y à 0 comme tu disais ?

Je parlais la de l'angle selon l'axe Y, comment la node tourne pour se déplacer.

mr.xyz Ecris:

  • rotateVect est de type void, je pense donc que tu voulais dire de créer un vector (0,1,0) et de le passer en passer en référence ?

Il y a plusieurs rotateVect, a toi de prendre celui qui t'arrange c'est pour ca que j'ai écrie en pseudo code juste pour d'indiquer la fonction à utiliser.

mr.xyz Ecris:

  • ensuite setRotation prends en paramètre un vecteur, donc je ne comprends pas "angle_souhaité*perso_y"

Ici perso_y c'est le vecteur recupéré par rotateVect. De toute maniere je viens de constater que j'ai oublier une etape, pour faire ce que je disais ; il faut passer par les quaternions , le code devient alors :

Code c++ :


vector3df v; //vecteur auxiliaire
quaternion q0,q1;
q0.rotationFromTo(vector3df(0,1,0),n); // n= la normale
q1.fromAngleAxis(Angle_Y_souhaitée*DEGTORAD,vector3df(0,1,0));
q1=q1*q0;
q1.toEuler(v);
node->setRotation(RADTODEG*v);

Sinon tu peux rajouter une composante de rotation selon Y comme tu disais c'est plus simple mais si la normale n'est pas proche de (0,1,0) il va y avoir de drôle de comportement, teste et adopte la méthode qui te convient le mieux.


Hors ligne


#12 

06-08-2010 09:20:03

mr.xyz
Membres
Date d'inscription:
Messages: 15
IP: 87.90.98.127
Courriel

Merci pour l'aide déja smile. Par contre cette méthode marche déja mieux que la dernière que tu proposais mais le node change parfois de direction (axe Y) brutalement 0o


Hors ligne


#13 

18-08-2010 22:36:41

mr.xyz
Membres
Date d'inscription:
Messages: 15
IP: 90.5.84.172
Courriel

Je n'arrive vraiment pas à trouver la bonne solution.. Depuis 2 semaines j'étais persuadé que la méthode atan2 marchait (j'avais rien remarqué de bizarre) mais aujourd'hui en m'approchant d'un bord de la map assez incliné, je me suis aperçu que le node n'était pas du tout bien incliné.

Bref, je m'y perds.. Pour être plus précis, je dirige une fourmi au clavier (comme un jeu de voitures).

z: avancer
s: reculer
q: rotation gauche
d: rotation droite

As tu déjà réussi à implémenter ça sur irrlicht ? Sa parait simple au premier abord (ayant fait beaucoup de jeux 2D je m'attendais pas à ça ^^ ) mais je trouve aucune solution, même sur les forums anglais...
Y a t-il un ordre dans l'exécution des évènements : d'abord les rotations en Y (direction) et ensuite X et Z (inclinaison) pour faciliter le code?

J'ai essayé la méthode des quaternions, et les autres dans tous les sens possibles, lu des cours de maths sur les matrices et les vecteurs.. Mais toujours aucune illumination pour incliner le node en fonction de la normale sad.

Bref, need help smile


Hors ligne


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