Physque pour Dreamotion3D

Généralités sur la programmation 3D
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Message par comtois »

Progi1984 a écrit :Comtois, tout juste 6h de sommeil et il écrit un moteur 3d lol
C'est exceptionnel, je me lève à 7h en général :)
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
tmyke
Messages : 1554
Inscription : lun. 24/juil./2006 6:44
Localisation : vosges (France) 47°54'39.06"N 6°20'06.39"E

Message par tmyke »

Désolé, je suis rentré dans la nuit.
J'ai donc essayé tes codes, la encore, cela ne semble pas fonctionner.
Dnas certains cas, on récupère bien les bon angles , mais dès que
l'on mixe trois angles avec des valeurs asser élevés, patatraque, c'est
plus bon.
:x

je me donne encore jusqu'a la fin du WE pour ariver a regler la chose
Force et sagesse...
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Message par comtois »

Pour améliorer les calculs , il y a la variable test à déclarer en flottant , j'ai oublié.

Code : Tout sélectionner

Procedure DecomposeRollPitchYawZXYMatrix()
;http://blogs.msdn.com/MikePelton/archive/2004/10/29/249501.aspx
;http://www.developpez.net/forums/showthread.php?t=160276&page=2
  angle_x = ASin(-mat\_32) 
   
  test.f = Cos(angle_x)
   
  angle_x * #RadDeg
   
  threshold.f = 0.001; // Hardcoded constant - burn him, he's a witch

  If(test <> threshold) 

    angle_z = Atan2(mat\_12, mat\_22) * #RadDeg

    angle_y = Atan2(mat\_31, mat\_33) * #RadDeg

  Else 

    angle_z = Atan2(-mat\_21, mat\_11) * #RadDeg

    angle_y = 0.0

  EndIf

EndProcedure

En fait le choix du quadrant est arbitraire, pour un sinus donné on a deux angles possibles et donc deux cos différents, faudrait voir s'il y a moyen d'extraire le cos dans la matrice pour vérifier dans quel quadrant on se situe.

voir aussi la discussion sur ce forum

Par contre , quand on utilise que le moteur graphique, les angles sont corrects ou pas ? je n'ai pas vérifié, je les utilise et je n'ai pas rencontré de problème pour l'instant.

Comment tu les calcules ces angles ? manifestement pas à partir de la matrice :)
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
tmyke
Messages : 1554
Inscription : lun. 24/juil./2006 6:44
Localisation : vosges (France) 47°54'39.06"N 6°20'06.39"E

Message par tmyke »

A l'heure actuelle, quand avec DM3D tu demande un rotation standart (DM_RotateEntity) le code executé est le suivant:

Code : Tout sélectionner

//--------------------------------------------------------------------------------------
//  fonction de Rotation 
//--------------------------------------------------------------------------------------
CEntity::Rotate(float x, float y, float z)
{
	D3DXQUATERNION cSc =D3DXQUATERNION(0.0,0.0,0.0,0.0);
	D3DXQUATERNION cQuat;
   
	rotation = D3DXVECTOR3(x,y,z);
	D3DXQuaternionRotationYawPitchRoll( &cQuat, rotation.x, rotation.y, rotation.z);
	D3DXMatrixTransformation( &mat_Scene,	&centre, &cSc, &scale, &centre,	&cQuat,	&translate);
}
Au niveau du moteur, cela fonctionne très bien et de plus c'est plutot optimisé
en therme de temps de calcul.
Le problème viens dès que tu veux récupérer les angles à partir de la matrice...

En attendant, je vais voir sur le forum dont tu donnes le lien.
Force et sagesse...
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Message par comtois »

voila le fameux lien que je n'avais pas réussi à faire fonctionner jusqu'à présent Matrice de passage et angles d'euler
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Message par comtois »

je m'étais dit qu'en déduisant le cos(x) de la matrice , et en ayant déjà en dispo le sin(x) , ça permettrait de déterminer à coup sûr dans quel quadrant se situe l'angle en x , ben non , même pas !!

Je tombe sur une racine carrée , du coup , deux quadrants sont possibles !

Code : Tout sélectionner

Sqr(((mat\_22*mat\_33)-(mat\_12*mat\_32*mat\_31))/mat\_11)
J'ai pas cherché pour les autres cos et sin, mais je m'attends à tomber aussi sur des racines carrées qui n'aideront pas plus !
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
tmyke
Messages : 1554
Inscription : lun. 24/juil./2006 6:44
Localisation : vosges (France) 47°54'39.06"N 6°20'06.39"E

Message par tmyke »

J'ai appenté une partie de la nuit le net en me disant que je finirais bien
par tomber sur un tuto ou un code qui sera viable, mais meme pas. :twisted:
Je continu a chercher, et j'analyse certains code que j'ai retrouvé dans mes archive...
Force et sagesse...
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Message par comtois »

j'ai fouillé dans les sources d'ogre
je n'ai pas encore regardé dans le détail , mais ... // WARNING. Not a unique solution. ... Je le crains :?

Code : Tout sélectionner

//-----------------------------------------------------------------------
    bool Matrix3::ToEulerAnglesXYZ (float& rfYAngle, float& rfPAngle,
        float& rfRAngle) const
    {
        // rot =  cy*cz          -cy*sz           sy
        //        cz*sx*sy+cx*sz  cx*cz-sx*sy*sz -cy*sx
        //       -cx*cz*sy+sx*sz  cz*sx+cx*sy*sz  cx*cy

        rfPAngle = Math::getSingleton().ASin(m[0][2]);
        if ( rfPAngle < Math::HALF_PI )
        {
            if ( rfPAngle > -Math::HALF_PI )
            {
                rfYAngle = Math::getSingleton().ATan2(-m[1][2],m[2][2]);
                rfRAngle = Math::getSingleton().ATan2(-m[0][1],m[0][0]);
                return true;
            }
            else
            {
                // WARNING.  Not a unique solution.
                float fRmY = Math::getSingleton().ATan2(m[1][0],m[1][1]);
                rfRAngle = 0.0;  // any angle works
                rfYAngle = rfRAngle - fRmY;
                return false;
            }
        }
        else
        {
            // WARNING.  Not a unique solution.
            float fRpY = Math::getSingleton().ATan2(m[1][0],m[1][1]);
            rfRAngle = 0.0;  // any angle works
            rfYAngle = fRpY - rfRAngle;
            return false;
        }
    }
    //-----------------------------------------------------------------------
    bool Matrix3::ToEulerAnglesXZY (float& rfYAngle, float& rfPAngle,
        float& rfRAngle) const
    {
        // rot =  cy*cz          -sz              cz*sy
        //        sx*sy+cx*cy*sz  cx*cz          -cy*sx+cx*sy*sz
        //       -cx*sy+cy*sx*sz  cz*sx           cx*cy+sx*sy*sz

        rfPAngle = Math::getSingleton().ASin(-m[0][1]);
        if ( rfPAngle < Math::HALF_PI )
        {
            if ( rfPAngle > -Math::HALF_PI )
            {
                rfYAngle = Math::getSingleton().ATan2(m[2][1],m[1][1]);
                rfRAngle = Math::getSingleton().ATan2(m[0][2],m[0][0]);
                return true;
            }
            else
            {
                // WARNING.  Not a unique solution.
                float fRmY = Math::getSingleton().ATan2(-m[2][0],m[2][2]);
                rfRAngle = 0.0;  // any angle works
                rfYAngle = rfRAngle - fRmY;
                return false;
            }
        }
        else
        {
            // WARNING.  Not a unique solution.
            float fRpY = Math::getSingleton().ATan2(-m[2][0],m[2][2]);
            rfRAngle = 0.0;  // any angle works
            rfYAngle = fRpY - rfRAngle;
            return false;
        }
    }
    //-----------------------------------------------------------------------
    bool Matrix3::ToEulerAnglesYXZ (float& rfYAngle, float& rfPAngle,
        float& rfRAngle) const
    {
        // rot =  cy*cz+sx*sy*sz  cz*sx*sy-cy*sz  cx*sy
        //        cx*sz           cx*cz          -sx
        //       -cz*sy+cy*sx*sz  cy*cz*sx+sy*sz  cx*cy

        rfPAngle = Math::getSingleton().ASin(-m[1][2]);
        if ( rfPAngle < Math::HALF_PI )
        {
            if ( rfPAngle > -Math::HALF_PI )
            {
                rfYAngle = Math::getSingleton().ATan2(m[0][2],m[2][2]);
                rfRAngle = Math::getSingleton().ATan2(m[1][0],m[1][1]);
                return true;
            }
            else
            {
                // WARNING.  Not a unique solution.
                float fRmY = Math::getSingleton().ATan2(-m[0][1],m[0][0]);
                rfRAngle = 0.0;  // any angle works
                rfYAngle = rfRAngle - fRmY;
                return false;
            }
        }
        else
        {
            // WARNING.  Not a unique solution.
            float fRpY = Math::getSingleton().ATan2(-m[0][1],m[0][0]);
            rfRAngle = 0.0;  // any angle works
            rfYAngle = fRpY - rfRAngle;
            return false;
        }
    }
    //-----------------------------------------------------------------------
    bool Matrix3::ToEulerAnglesYZX (float& rfYAngle, float& rfPAngle,
        float& rfRAngle) const
    {
        // rot =  cy*cz           sx*sy-cx*cy*sz  cx*sy+cy*sx*sz
        //        sz              cx*cz          -cz*sx
        //       -cz*sy           cy*sx+cx*sy*sz  cx*cy-sx*sy*sz

        rfPAngle = Math::getSingleton().ASin(m[1][0]);
        if ( rfPAngle < Math::HALF_PI )
        {
            if ( rfPAngle > -Math::HALF_PI )
            {
                rfYAngle = Math::getSingleton().ATan2(-m[2][0],m[0][0]);
                rfRAngle = Math::getSingleton().ATan2(-m[1][2],m[1][1]);
                return true;
            }
            else
            {
                // WARNING.  Not a unique solution.
                float fRmY = Math::getSingleton().ATan2(m[2][1],m[2][2]);
                rfRAngle = 0.0;  // any angle works
                rfYAngle = rfRAngle - fRmY;
                return false;
            }
        }
        else
        {
            // WARNING.  Not a unique solution.
            float fRpY = Math::getSingleton().ATan2(m[2][1],m[2][2]);
            rfRAngle = 0.0;  // any angle works
            rfYAngle = fRpY - rfRAngle;
            return false;
        }
    }
    //-----------------------------------------------------------------------
    bool Matrix3::ToEulerAnglesZXY (float& rfYAngle, float& rfPAngle,
        float& rfRAngle) const
    {
        // rot =  cy*cz-sx*sy*sz -cx*sz           cz*sy+cy*sx*sz
        //        cz*sx*sy+cy*sz  cx*cz          -cy*cz*sx+sy*sz
        //       -cx*sy           sx              cx*cy

        rfPAngle = Math::getSingleton().ASin(m[2][1]);
        if ( rfPAngle < Math::HALF_PI )
        {
            if ( rfPAngle > -Math::HALF_PI )
            {
                rfYAngle = Math::getSingleton().ATan2(-m[0][1],m[1][1]);
                rfRAngle = Math::getSingleton().ATan2(-m[2][0],m[2][2]);
                return true;
            }
            else
            {
                // WARNING.  Not a unique solution.
                float fRmY = Math::getSingleton().ATan2(m[0][2],m[0][0]);
                rfRAngle = 0.0;  // any angle works
                rfYAngle = rfRAngle - fRmY;
                return false;
            }
        }
        else
        {
            // WARNING.  Not a unique solution.
            float fRpY = Math::getSingleton().ATan2(m[0][2],m[0][0]);
            rfRAngle = 0.0;  // any angle works
            rfYAngle = fRpY - rfRAngle;
            return false;
        }
    }
    //-----------------------------------------------------------------------
    bool Matrix3::ToEulerAnglesZYX (float& rfYAngle, float& rfPAngle,
        float& rfRAngle) const
    {
        // rot =  cy*cz           cz*sx*sy-cx*sz  cx*cz*sy+sx*sz
        //        cy*sz           cx*cz+sx*sy*sz -cz*sx+cx*sy*sz
        //       -sy              cy*sx           cx*cy

        rfPAngle = Math::getSingleton().ASin(-m[2][0]);
        if ( rfPAngle < Math::HALF_PI )
        {
            if ( rfPAngle > -Math::HALF_PI )
            {
                rfYAngle = Math::getSingleton().ATan2(m[1][0],m[0][0]);
                rfRAngle = Math::getSingleton().ATan2(m[2][1],m[2][2]);
                return true;
            }
            else
            {
                // WARNING.  Not a unique solution.
                float fRmY = Math::getSingleton().ATan2(-m[0][1],m[0][2]);
                rfRAngle = 0.0;  // any angle works
                rfYAngle = rfRAngle - fRmY;
                return false;
            }
        }
        else
        {
            // WARNING.  Not a unique solution.
            float fRpY = Math::getSingleton().ATan2(-m[0][1],m[0][2]);
            rfRAngle = 0.0;  // any angle works
            rfYAngle = fRpY - rfRAngle;
            return false;
        }
    }
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
tmyke
Messages : 1554
Inscription : lun. 24/juil./2006 6:44
Localisation : vosges (France) 47°54'39.06"N 6°20'06.39"E

Message par tmyke »

Oui, j'ai fais pareil, y compris dans le code du 'torque engine', en fait
il ne semble pas y avoir de solution 'unique'. J'ai poste sur 'developpez.net'
pour savoir si quelqu'un a une amorce de solution par rapport au FAQ du meme site...
En espérant une amorce de solution...
Sinon je continue a chercher en attendant :twisted:
Force et sagesse...
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Message par comtois »

Je suis en train de lire ça
http://www.ogre3d.org/wiki/index.php/Qu ... ion_Primer

et en faisant une recherche sur angle euler sur le forum d'ogre , on trouve pas mal de lien , reste à voir s'il y a la bonne info dans tout ça !
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Message par comtois »

en passant par le quaternion j'obtiens l'angle x, reste à trouver le reste :)

Code : Tout sélectionner

; Fichiers Include
IncludePath "..\Include\"
IncludeFile "d3dx9.pbi"

#RadDeg = 180.0  / #PI
#DegRad =  #PI / 180.0
#HALF_PI = #PI /2.0


x.f =  95 * #DegRad
y.f =  65 * #DegRad
z.f =  34 * #DegRad

D3DXQuaternionRotationYawPitchRoll( @cQuat.D3DXQUATERNION, x, y, z) 

Debug StrF(cQuat\x,1) + " " + StrF(cQuat\y,1) + " " +StrF(cQuat\z,1) + " " +StrF(cQuat\w,1) 
Debug "Angle x = " + StrF(2 * ACos(cQuat\w) * #RadDeg,3)
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Message par comtois »

j'avais repris ton exemple pour la rotation avec un quaternion , mais tu n'as pas inversé le y et le x ?

YawPitchRoll c'est YXZ non ?

Code : Tout sélectionner

; Fichiers Include
IncludePath "..\Include\"
IncludeFile "d3dx9.pbi"

#RadDeg  = 180.0 / #PI
#DegRad  = #PI   / 180.0
#HALF_PI = #PI   / 2.0


x.f =  50 * #DegRad
y.f =  -57 * #DegRad
z.f =  94 * #DegRad

D3DXQuaternionRotationYawPitchRoll( @cQuat.D3DXQUATERNION, y, x, z) 

Debug StrF(cQuat\x,3) + " " + StrF(cQuat\y,3) + " " +StrF(cQuat\z,3) + " " +StrF(cQuat\w,3) 
Debug "Angle y = " + StrF(2 * ACos(cQuat\w) * #RadDeg, 3)
Debug "Angle y = " + StrF(2 * ASin(cQuat\y) * #RadDeg, 3)
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Message par djes »

Question bête. Pourquoi ne pas définir trois axes par objets, et tourner ensuite l'objet par rapport à ceux-ci. Ainsi, la combinaison rotation des axes+rotation de l'objet serait reproductible (enfin je pense).
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Message par comtois »

djes a écrit :Question bête. Pourquoi ne pas définir trois axes par objets, et tourner ensuite l'objet par rapport à ceux-ci. Ainsi, la combinaison rotation des axes+rotation de l'objet serait reproductible (enfin je pense).
Parce que le moteur physique ne connait que la matrice pour agir sur les entitys, et c'est cette matrice qu'il faut interpréter pour retrouver les angles.

bon j'ai fini par télécharger l'ensemble des sources d'ogre, je n'avais jusqu'ici que la version édulcorée adaptée à purebasic.

Voila à quoi ressemble les fonctions qui donnent les angles.
ça ne fonctionne pas chez moi, mais c'est intéressant de se plonger dedans :)

Faut que je regarde la fonction GetOrientation()

Code : Tout sélectionner

	Radian Quaternion::getRoll(void) const
	{
		return Radian(Math::ATan2(2*(x*y + w*z), w*w + x*x - y*y - z*z));
	}
    //-----------------------------------------------------------------------
	Radian Quaternion::getPitch(void) const
	{
		return Radian(Math::ATan2(2*(y*z + w*x), w*w - x*x - y*y + z*z));
	}
    //-----------------------------------------------------------------------
	Radian Quaternion::getYaw(void) const
	{
		return Radian(Math::ASin(-2*(x*z - w*y)));
	}
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Message par comtois »

je ne sais pas si ça va servir , mais j'ai appris plein de trucs au passage :)

Faudra vérifier dans le fichier d3dx9math.pbi il me semble que j'ai corrigé une déclaration , c'était des pointeurs avant je crois ?

Code : Tout sélectionner

D3DXQuaternionRotationYawPitchRoll.l(*pOut.D3DXQUATERNION, Yaw.f, Pitch.f, Roll.f)

Code : Tout sélectionner

; Fichiers Include
IncludePath "..\Include\"
IncludeFile "d3dx9.pbi"

Declare.f getRoll(*cQuat.D3DXQUATERNION) 
Declare.f getPitch(*cQuat.D3DXQUATERNION) 
Declare.f getYaw(*cQuat.D3DXQUATERNION) 
Declare.f atan2(y.d,x.d)

Define.D3DXQUATERNION Pitch, Yaw, Roll, pout 
Define.D3DXMATRIX mat

#RadDeg  = 180.0 / #PI
#DegRad  = #PI   / 180.0
#HALF_PI = #PI   / 2.0

;- Saisir les angles ici
x.f =  65 * #DegRad
y.f =  -67 * #DegRad
z.f =  93 * #DegRad

;Rotation axe par axe 
D3DXQuaternionRotationYawPitchRoll(Pitch, 0, x, 0) 
D3DXQuaternionRotationYawPitchRoll(Yaw  , y, 0, 0) 
D3DXQuaternionRotationYawPitchRoll(Roll , 0, 0, z) 
;Affiche le résultat
Debug StrF(getPitch(Pitch) * #RadDeg, 2)
Debug StrF(getYaw(Yaw)     * #RadDeg, 2)
Debug StrF(getRoll(Roll)   * #RadDeg, 2)
Debug "---"

;Un quaternion regroupant toutes les rotations
D3DXQuaternionMultiply.l(@pOut, @Pitch, @Yaw)
D3DXQuaternionMultiply.l(@pOut, @pOut, @Roll)    
;Affiche le résultat
Debug StrF(getPitch(@pOut) * #RadDeg, 2)
Debug StrF(getYaw(@pOut)   * #RadDeg, 2)
Debug StrF(getRoll(@pOut)  * #RadDeg, 2)
Debug "---"

; ;Matrice de rotation
; D3DXMatrixRotationYawPitchRoll(@mat, y, x, z)
; ;Repasse par le quaternion pour voir
; D3DXQuaternionRotationMatrix.l(@pOut, @mat)
; Debug getPitch(@pOut) * #RadDeg
; Debug getYaw(@pOut)   * #RadDeg
; Debug getRoll(@pOut)  * #RadDeg
; Debug "---"

End

Procedure.f atan2(y.d,x.d)
;atan2 procedure by Paul Dixon
;http://www.powerbasic.com/support/forums/Forum4/HTML/009180.html
;adapted to PureBasic by Jack
! fld qword [p.v_y] ;load y
! fld qword [p.v_x] ;load x
! fpatan ;get atan(y/x), put result in ST1. then pop stack to leave result in ST0
;! ftst ;test ST0 (that's the top of stack) against zero
;! fstsw ax ;put result of test into AX
;! sahf ;get the FPU flags into the CPU flags
;! jae @@skip ; if above or equal then skip the add 2*pi code
;! fldpi ;get pi
;! fadd st1,st0 ;add pi to result
;! faddp st1,st0 ;and again, for 2pi, then pop the now unneeded pi from st0
;! @@skip:
ProcedureReturn
EndProcedure
Procedure.f getRoll(*cQuat.D3DXQUATERNION) 
  ProcedureReturn ATan2(2*(*cQuat\x * *cQuat\y + *cQuat\w * *cQuat\z), *cQuat\w * *cQuat\w + *cQuat\x * *cQuat\x - *cQuat\y * *cQuat\y - *cQuat\z * *cQuat\z)
EndProcedure

Procedure.f getPitch(*cQuat.D3DXQUATERNION) 
	ProcedureReturn ATan2(2*(*cQuat\y * *cQuat\z + *cQuat\w * *cQuat\x), *cQuat\w * *cQuat\w - *cQuat\x * *cQuat\x - *cQuat\y * *cQuat\y + *cQuat\z * *cQuat\z)
EndProcedure

Procedure.f getYaw(*cQuat.D3DXQUATERNION) 
	ProcedureReturn ASin(-2*(*cQuat\x * *cQuat\z - *cQuat\w * *cQuat\y))
EndProcedure
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
Répondre