Bonjour, j'utilise la classe d'un membre de ce forum (je l'en remercie beaucoup) : Zangetsu qui permet à la caméra d'être positionnée tout le temps derrière le personnage.
J'ai crée une fonction qui permet de faire tourner/déplacer le personnage en fonction des touches tapées au clavier:
void CEventReceiver::majOfPos() { if(Nmodele != 0 && isMoving == true) { irr::core::vector3df vector = Nmodele->getRotation(); irr::core::vector3df v = Nmodele->getPosition(); if(move == forward) { v.X += 1.0f; } else if(move == backward) { v.X -= 1.0f; } else if(move == left) { v.Z += 1.0f; } else if(move == right) { v.Z -= 1.0f; } else if(move == turnLeft) { vector.Y--; } else if(move == turnRight) { vector.Y++; } Nmodele->setRotation(irr::core::vector3df(vector.X, vector.Y, vector.Z)); Nmodele->setPosition(v); } }
Le personnage avance et tourne bien correctement (la caméra le suit parfaitement).
Où est le problème ? Il est étrange, quand je n'effectue pas de rotation, le personnage avance correctement (z pour devant, s pour derrière, q pour la gauche et d pour la droite). Dès que j'effectue une rotation, le déplacement est modifié (z provoque un déplacement différent de celui demandé, idem pour les 3 autres touches). Si je reviens "en position initiale" tout refonctionne.
Merci d'avance
PS: Pour les noms de fonctions, de classes... Si vous êtes perturbé c'est normal, le programme que je développe est une sorte de "prototype" juste pour voir de quoi est capable le moteur, du moins de quoi je suis capable de faire avec ce moteur donc sur le projet final les variables seront mieux nommées, les classes plus explicites...
Dernière modification par samsoft (11-06-2008 08:50:36)
Hors ligne
Salut,
La réponse se trouve plus dans un cours de math qu'autre chose. En effet les vecteurs de positions et de rotation sont absolues. Donc quand tu augmente z augmente la profondeur de ton personnage par rapport à l'origine du repère, il ne tient pas conte de la rotation qui a été appliqué à ton model. C'est à dire que si tu tourne ton perso de 30° quand il va avancer se serat sur une droite qui fait 30° par rapport à l'axe des z et non sur l'axe des z.
C'est à dire qu'il te faut faire de la trigonométrie.
Tu dois faire quelque chose comme ca(a confirmer car je n'est jamais vraiment tester) :
if(move == forward) { v.X += sin(vector.Y); v.Z += cos(vector.Y); } else if(move == backward) { v.X += sin(vector.Y + 180); v.Z += cos(vector.Y + 180); } else if(move == left) { v.X += sin(vector.Y + 90); v.Z += cos(vector.Y + 90); } else if(move == right) { v.X += sin(vector.Y - 90); v.Z += cos(vector.Y - 90); } else if(move == turnLeft) { vector.Y--; } else if(move == turnRight) { vector.Y++; }
J'ai supposé que les fonctions cos et sin marchait avec des deugré et que getrotation renvoyait aussi des deugrés si tel n'était pas le cas il faudrait modifier en conséquence les fonctions en remplacant 180 par pi et 90 par pi/2 et convertir les angles.
En espérant avoir aidé même si je suis pas sur de tout.
Dark calculator
Hors ligne
N'ayant que 16 ans et programmant par passion, je ne pouvais pas prévoir (je n'y avais pas pensé) ce cas là.
Je vais voir cela, au pire je me fais une fonction qui transforme des radians (pourvu que ce ne soit pas des gradients) en degrés (j'ai programmé ca en basic sur ma calculette )
Merci, je test cela
EDIT: Ca ne fonctionne pas comme prévue, le résultat est le même qu'avec le code posté au premier message. Pour faire simple, j'ai supprimé left et right qui en réalité ne sont pas réalistes et gardé forward et backward:
if(move == forward) { v.X += sin(vector.Y + 180); v.Z += cos(vector.Y + 180); } else if(move == backward) { v.X += sin(vector.Y - 180); v.Z += cos(vector.Y - 180); } else if(move == turnLeft) { vector.Y--; } else if(move == turnRight) { vector.Y++; }
PS:
Dans vector3d j'ai vu plusieurs fois degres.
J'ai testé avec 3.1415/2 aussi
Dernière modification par samsoft (11-06-2008 10:55:10)
Hors ligne
Il font quoi au lycée de nos jours ...
Si tu commences à toucher a la programmation orientée 3D il va obligatoirement te falloir les bases en mathematique de l'espace : vecteur et trigonometrie et plus tard matrice.
Il y a 3 types de repere : le local , le global , et le repere parent , ce dernier tu peux l'oublier pour le moment.
Le global ne bouge pas , ne tourne pas ,il a toujour au centre du monde : (0,0,0) ( orientation non directe ).
Le Local tourne et bougge avec l'objet ( ici Nmodele ) il lui est accroché.
Donc quand tu tournes puis que tu avances ( v.Z +=1.0f ) l'axe d'avancement est celui du repere global alors qu'il faudrait que se soit celui du local afin de tenir compte de la rotation faite.
Le plus simple et si la node n'a qu'une seul rotation possible ,c'est d'utiliser la trigornometrie :
Dernière modification par firnafin (11-06-2008 12:02:38)
Hors ligne
Je crois saisir votre concept de local, global. Mais même avec votre code, cela ne roule pas
void CEventReceiver::majOfPos() { if(Nmodele != 0 && isMoving == true) { irr::core::vector3df rot = Nmodele->getRotation(); irr::core::vector3df axe_z_local = irr::core::vector3df(cos(rot.Y), 0, sin(rot.Y)); axe_z_local.normalize(); if(move == forward) { Nmodele->setPosition(Nmodele->getPosition()+axe_z_local); } else if(move == backward) { Nmodele->setPosition(Nmodele->getPosition()-axe_z_local); } else if(move == turnLeft) { rot.Y--; } else if(move == turnRight) { rot.Y++; } Nmodele->setRotation(irr::core::vector3df(rot.X, rot.Y, rot.Z)); } }
J'ai vérifie, c'est bien la variable Y qu'il faut modifier.
axe_z_local.normalize();
Veut il dire qu'on transforme les coordonnées en norme ?
Faut il uniquement utiliser le vecteur_z ?
PS: Au lycée ben moi j'ai vu vecteur... (2d et 3d pour coordonnées) là je suis en prem S mais pas de rotation (c'est en term) et puis l'arithémique/analyse (suite, fonction, proba) j'adore ca mais la géométrique (excepté l'analytique qui ressemble à la physique) j'aime pas
Dernière modification par samsoft (11-06-2008 12:33:29)
Hors ligne
C'est un peu mieu , j'avais ecri le chagement pour l'axe X .
A part ca , ca devrait marcher.
Le
axe_z_local.normalize()
c'etait juste pour le normaliser mais c'est inutile , il est deja de norme 1.
samsoft :
Faut-il uniquement utiliser le vecteur_z ?
Bien si tu veux avancer seulement oui , si tu veux translater a droite ou a gauche il faut la meme chose avec le vecteur x .
Hors ligne
C'est un peu mieu , j'avais ecri le chagement pour l'axe X hmm.
A part ca , ca devrait marcher.
Toujours pas :p
Bien si tu veux avancer seulement oui , si tu veux translater a droite ou a gauche il faut la meme chose avec le vecteur x .
C'est que je suis borné pour moi z est la profondeur, x en bas et y en haut mais en 3d tout change (tout tourne)
Ouai avancer et reculer, c'est uniquement ce dont j'ai besoin.
Voilà le code :
void CEventReceiver::majOfPos() { if(Nmodele != 0 && isMoving == true) { irr::core::vector3df rot = Nmodele->getRotation(); irr::core::vector3df axe_z_local = irr::core::vector3df(-sin(rot.Y), 0, cos(rot.Y)); if(move == forward) { Nmodele->setPosition(Nmodele->getPosition()+axe_z_local); } else if(move == backward) { Nmodele->setPosition(Nmodele->getPosition()-axe_z_local); } else if(move == turnLeft) { rot.Y--; } else if(move == turnRight) { rot.Y++; } Nmodele->setRotation(irr::core::vector3df(rot.X, rot.Y, rot.Z)); } }
Si j'ai bien suivi, le problème se situe ici :
Merci pour tout et d'avance,
Hors ligne
i pi pi Hourra ! J'ai réussi grâce à vous (et à mon prof de proba) Alors comme je n'ai pas (encore) les connaissances pour parvenir de manière raisonnée à mon problème j'ai utilisé un arbre (c'est là que je dis thx à mon prof de maths) pour tester les différentes possibilités de :
J'ai dis que 1 = cos(rot.Y*3.1415f/180.0f) ; 2 = 0 et 3 = sin(rot.Y*3.1415f/180.0f);
A l'aide de mon arbre j'ai testé toutes les possibilités et j'ai trouvé que 3-2-1 était la plus probable.
Cependant, ça ne fonctionnait toujours pas alors je me suis souvenu du moins que vous aviez placé, j'ai pas compris (de manière mathématique) pourquoi mais de manière logique j'ai compris.
En effet, mon perso allez dans la diagonale "opposée" au déplacement voulu j'ai donc mis un moins à sin pour régler ce problème.
Résolu,
Encore merci
void CEventReceiver::majOfPos() { if(Nmodele != 0 && isMoving == true) { irr::core::vector3df rot = Nmodele->getRotation(); irr::core::vector3df axe_z_local = irr::core::vector3df(cos(rot.Y*3.1415f/180.0f), 0, -sin(rot.Y*3.1415f/180.0f)); if(move == forward) { Nmodele->setPosition(Nmodele->getPosition()+axe_z_local); } else if(move == backward) { Nmodele->setPosition(Nmodele->getPosition()-axe_z_local); } else if(move == turnLeft) { rot.Y--; } else if(move == turnRight) { rot.Y++; } Nmodele->setRotation(irr::core::vector3df(rot.X, rot.Y, rot.Z)); } }
Dernière modification par samsoft (11-06-2008 18:23:54)
Hors ligne
samsoft :
2 = 0
euh ... il me semble que non ( je suis licencié de math pourtant )
Hors ligne
Ah non, je voulais dire:
Cas 1 = ...
Cas 2 = 0
lol
Hors ligne
Pour ma part j'utilise cette methode :
irr::core::matrix4 Mat; if (m_Nmodele != 0 && m_isMoving == true) { //On commence par recuperer la position actuelle core::vector3df v = m_Nmodele->getPosition(); core::vector3df r = m_Nmodele->getRotation(); if (myKeyPressed=="Z") { //On y ajoute la valeur de deplacement Mat.setRotationDegrees(m_Nmodele->getRotation()); core::vector3df Target(0.2,0,0); Mat.transformVect(Target); core::vector3df NewPos=m_Nmodele->getPosition(); NewPos += Target; m_Nmodele->setPosition(NewPos); } else if (myKeyPressed=="S") { Mat.setRotationDegrees(m_Nmodele->getRotation()); core::vector3df Target(-0.2,0,0); Mat.transformVect(Target); core::vector3df NewPos=m_Nmodele->getPosition(); NewPos += Target; m_Nmodele->setPosition(NewPos); } if (myKeyPressed=="Q") { r.Y-= 0.1; m_Nmodele->setRotation(r); } else if (myKeyPressed=="D") { r.Y+= 0.1; m_Nmodele->setRotation(r); } }
Hors ligne
Ouai, j'ai entendu parler des matrices (comme méthode alternative), cependant, les matrices on les voit en premiere ES et moi je suis en S. De plus ma méthode est plus courte
Mais merci quand même, elle doit être meilleur
Hors ligne
oui c'était surtout histoire de montrer une autre magnière de faire qui peut s'avérer très utile dans d'autre cas
Hors ligne
les matrices on les voit en premier ES et moi je suis en S
Je ne sais pas d'ou tu sorts ca, les matrices sont abordées en bac +1 en général.De toute maniere si tu ne comptes pas apprendre par toi meme et attendre que "l'école" t'enseigne alors tu es mal barré.Les matrices c'est tres simple conceptuellement ,comprendre comment s'en servir aussi , la theorie est plus lourde mais en prog l'avantage c'est que la théorie on la met la ou je pense. Essaye de comprendre le code de nikska car la trigo c'est vraiment pour faire de la bidouille.
Hors ligne
Un ami en première ES m'a dit cela après moi je suis pas en première ES. En fait, après le bac français, je compte apprendre la 3D (matrices, vecteurs) du moins de manière simplifiée juste pour m'aider à régler les futurs problèmes éventuels.
tu es mal barré
Je fais cela par passion (sur mon temps libre), je compte devenir ingénieur informaticien ("catégorie": programmeur) donc en gros là je suis assez "en avance" après à "l'école" je vais tout réapprendre donc pas de soucis à ce niveau là
Je viens de trouver une "preuve" de l'apprentissage des matrices en ES :
http://yallouz.arie.free.fr/premiere_co … 6_2007.php
Après on parle peut être pas de la même chose
Dernière modification par samsoft (12-06-2008 14:30:42)
Hors ligne
Effectivement les "éco" voient les matrices en maths au lycée et pas les S
J'ai toujours trouvé ça stupide mais bon... avec les programmes de maths bien chargés qu'on avait au lycée, on va pas s'en plaindre.
Par contre je confirme aussi que tu es amené à revoir les matrices dans le supérieur
Hors ligne
"A ouaih" ... et en es en plus ..seulement depuis 2002 (j'ai raté ca , je suis trop vieux ) .Pas super pédagogique je trouve de voir les matrices ss parler d'espace vectoriel et tout le blabla de l'algebre linéaire ; on aura tout vu ... et dire que je vais devenir prof
Hors ligne