#0 

29-07-2010 17:53:23

mr.xyz
Membre
Date d'inscription: 01-07-2010
Messages: 15

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();
    }

Dernière modification par mr.xyz (29-07-2010 17:54:12)

Hors ligne


#1 

29-07-2010 21:52:48

firnafin
Abonné
Date d'inscription: 31-03-2007
Messages: 150

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.

Dernière modification par firnafin (29-07-2010 21:53:59)

Hors ligne


#2 

30-07-2010 00:32:10

mr.xyz
Membre
Date d'inscription: 01-07-2010
Messages: 15

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


#3 

30-07-2010 11:59:50

firnafin
Abonné
Date d'inscription: 31-03-2007
Messages: 150

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.

Dernière modification par firnafin (30-07-2010 15:10:25)

Hors ligne


#4 

30-07-2010 14:38:45

mr.xyz
Membre
Date d'inscription: 01-07-2010
Messages: 15

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);

Dernière modification par mr.xyz (30-07-2010 14:39:23)

Hors ligne


#5 

30-07-2010 14:48:49

mr.xyz
Membre
Date d'inscription: 01-07-2010
Messages: 15

firnafin :

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


#6 

30-07-2010 15:04:08

firnafin
Abonné
Date d'inscription: 31-03-2007
Messages: 150

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

Dernière modification par firnafin (30-07-2010 15:06:07)

Hors ligne


#7 

30-07-2010 15:44:23

mr.xyz
Membre
Date d'inscription: 01-07-2010
Messages: 15

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


#8 

30-07-2010 15:57:19

firnafin
Abonné
Date d'inscription: 31-03-2007
Messages: 150

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


#9 

05-08-2010 16:10:56

mr.xyz
Membre
Date d'inscription: 01-07-2010
Messages: 15

firnafin :

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 :

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

Dernière modification par mr.xyz (05-08-2010 18:32:43)

Hors ligne


#10 

06-08-2010 00:13:11

firnafin
Abonné
Date d'inscription: 31-03-2007
Messages: 150

mr.xyz :

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

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


celle du terrain.

mr.xyz :

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


oui

mr.xyz :

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

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

- 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


#11 

06-08-2010 11:20:03

mr.xyz
Membre
Date d'inscription: 01-07-2010
Messages: 15

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


#12 

19-08-2010 00:36:41

mr.xyz
Membre
Date d'inscription: 01-07-2010
Messages: 15

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

Dernière modification par mr.xyz (19-08-2010 00:40:25)

Hors ligne


Options Liens officiels Caractéristiques Statistiques Communauté
Corrections
irrlicht
irrklang
irredit
irrxml
xhtml 1.0
css 2.1
Propulsé par FluxBB
Traduit par FluxBB.fr
881 membres
1426 sujets
11116 messages
Dernier membre inscrit: Bidule
21 invités en ligne
Aucun membre connecté
RSS Feed