Physque pour Dreamotion3D
tiens j'avais posté une serie d'articles qui peuvent t'interesser :
http://www.mandragor.org/tutoriels/3d/0
http://membres.lycos.fr/javamus/articles/mqfaq.html
http://cours-info.iut-bm.univ-fcomte.fr ... ib/tp5.pdf
http://www.onversity.net/cgi-bin/progar ... =a1405#080
http://eraquila.iquebec.com/site/theo/matrice.htm
http://www.mandragor.org/tutoriels/3d/0
http://membres.lycos.fr/javamus/articles/mqfaq.html
http://cours-info.iut-bm.univ-fcomte.fr ... ib/tp5.pdf
http://www.onversity.net/cgi-bin/progar ... =a1405#080
http://eraquila.iquebec.com/site/theo/matrice.htm
Je présume que tu passe par le produit matricielle pour touver la matrice concaténée des 3 rotations. Si tu utilise les Quaternions pour les calculs de rotation, tu va être en mesure de créer une matrice de rotation plus précise en faisant moins d'opérations mathématiques. Et tu sais très bien qu'un moteur 3D, ça en fait des calculs par secondes.tmyke a écrit :Merci pour vos conseil et lien. Je mate cela et je vois comment m'en sortir.
La j'ai fait un petit code simple. J'ai un cube sur lequel j'applique une rotation
sur les 3 axes, et je récupère les angles a partir de la matrice de transformation
pour les appliquer a un second cube. En théorie, je devrais obtenir les memes
rotations. Force est d'avouer que pour l'instant ce n'est pas le cas.
Alors je travaille mon truc...
Sur ce, bonne chance !
A+
Guimauve
- Progi1984
- Messages : 2659
- Inscription : mar. 14/déc./2004 13:56
- Localisation : France > Rennes
- Contact :
A tes souhaits !
Librairies & Applications : https://www.purebasic.fr/french/viewtop ... f=8&t=6220
Site Web : https://rootslabs.net
Site Web : https://rootslabs.net
-
- Messages : 1554
- Inscription : lun. 24/juil./2006 6:44
- Localisation : vosges (France) 47°54'39.06"N 6°20'06.39"E
Merci Progi
sinon, j'ai par exemple mis en pratique les calculs que l'on trouve dans le lien
http://jeux.developpez.com/faq/matquat/ ... ations#Q37
et la aussi, les angles transmis ne sont pas récupéres correctement...
donc pas si simple la chose, mais je continue a creusr..

sinon, j'ai par exemple mis en pratique les calculs que l'on trouve dans le lien
http://jeux.developpez.com/faq/matquat/ ... ations#Q37
et la aussi, les angles transmis ne sont pas récupéres correctement...
donc pas si simple la chose, mais je continue a creusr..

Force et sagesse...
euh, le fait que tu sois en trièdre inverse, ça n'a rien à voir ?
Peut-être que l'exemple est donné pour un repère avec un trièdre direct ?
ça change quelque chose dans les calculs ?
Peut-être que l'exemple est donné pour un repère avec un trièdre direct ?
ça change quelque chose dans les calculs ?
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.
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
j'ai voulu afficher la matrice de la caisse en reprenant ton exemple
c'est bizarre cette valeur 3 dans mat\_42 non ?
A part ça j'ai voulu essayer et j'obtiens les bons angles si je ne fais que des rotations en x ou / et z, ou en y seul, si je mets les 3 ensembles le résultat n'est pas bon.
c'est bizarre cette valeur 3 dans mat\_42 non ?
A part ça j'ai voulu essayer et j'obtiens les bons angles si je ne fais que des rotations en x ou / et z, ou en y seul, si je mets les 3 ensembles le résultat n'est pas bon.
Code : Tout sélectionner
; Fichiers Include
IncludePath "..\Include\"
IncludeFile "d3dx9.pbi"
IncludeFile "dreamotion3d.pbi"
IncludeFile "PhysX.pbi"
; Globales
Global anglex.f, angley.f, flagXDown.w
Global mox.f, omx.f, moy.l, omy.l
Global angle_y.f,angle_x.f, angle_z.f
Global *camera.CEntity
Global Dim *roue.CEntity(4)
Global Dim *axis.CEntity(4)
Global *font.CFont
Global *caisse
Global *joint.NxJoint
Global *joint2.NxJoint
Global mat.D3DXMATRIX
Macro NEW_X(x, Angle, Distance)
((x) + Cos((Angle) * 0.0174533) * (Distance))
EndMacro
Macro NEW_Z(z, Angle, Distance)
((z) - Sin((Angle) * 0.0174533) * (Distance))
EndMacro
;- Declaration des procédures
Declare.f CurveValue(actuelle.f, Cible.f, P.f)
Declare GestionCamera()
; Initialisation des différents modules
If InitSprite() = 0 Or InitKeyboard() = 0 Or InitMouse() = 0
End
EndIf
; Initialise la fenêtre graphique
DM_Graphics3D(800, 600, 32, 0, 1)
; Charge une font
*font = DM_LoadFont("Arial",8 , 1)
DM_SetColorText (*font, 198,198,198,255)
DM_AmbiantLight(150, 150, 150)
SetCurrentDirectory("medias/")
;---------------------------------
; INIT DU MOTEUR PHYSIQUE
;---------------------------------
NX_Init(*DM_d3dDev9)
;--------------------------------------------------------------
; PETITE LIGHT HISTOIRE DE ...
;--------------------------------------------------------------
*light = DM_CreateLight(3, #Null)
;--------------------------------------------------------------
; set ground
;--------------------------------------------------------------
*ter = DM_LoadEntity("land3.x", #Null, #False)
DM_TranslateEntity(*ter, 0,20,0)
NX_CreateStaticElement(*ter,10, 2)
*ter = DM_CreateSphere(4)
DM_ScaleMesh(*ter, 30,30,30)
DM_TranslateEntity(*ter, 0,-35,100)
NX_CreateStaticElement(*ter,10, 2)
*brush = DM_GetBrush(*ter)
DM_LoadTexture( DM_GetTexture(*brush), "grille1.bmp")
*caisse = DM_CreateCube()
DM_ScaleMesh(*caisse, 4, 2,8)
DM_TranslateEntity(*caisse, 0,3,0)
NX_CreatePhysicBox(*caisse, 0,0,0, 5000.0,0)
For i = 0 To 3
*roue(i) = DM_CreateCylinder(16)
DM_ScaleMesh(*roue(i), 2,2,0.25)
DM_RotateMesh(*roue(i), 0,90,0)
Next
DM_TranslateEntity(*roue(0), 6,0,7) : NX_CreatePhysicMesh(*roue(0), 400,2) : NX_EntitySetContact(*roue(0), *caisse, 0)
DM_TranslateEntity(*roue(1), 6,0,-7): NX_CreatePhysicMesh(*roue(1), 400,2) : NX_EntitySetContact(*roue(1), *caisse, 0)
DM_TranslateEntity(*roue(2), -6,0,7): NX_CreatePhysicMesh(*roue(2), 400,2) : NX_EntitySetContact(*roue(2), *caisse, 0)
DM_TranslateEntity(*roue(3), -6,0,-7): NX_CreatePhysicMesh(*roue(3), 400,2) : NX_EntitySetContact(*roue(3), *caisse, 0)
For i = 0 To 3
*axis(i) = DM_CreateSphere(8)
DM_ScaleMesh(*axis(i), 0.45,0.45, 0.45)
Next
DM_TranslateEntity(*axis(0), 4,0,7) : NX_CreatePhysicSphere(*axis(0), 0,400,0)
NX_EntitySetContact(*axis(0), *caisse, 0)
NX_EntitySetContact(*axis(0), *roue(0), 0)
DM_TranslateEntity(*axis(1), 4,0,-7): NX_CreatePhysicSphere(*axis(1), 0,400,0)
NX_EntitySetContact(*axis(1), *caisse, 0)
NX_EntitySetContact(*axis(1), *roue(1), 0)
DM_TranslateEntity(*axis(2), -4,0,7): NX_CreatePhysicSphere(*axis(2), 0,400,0)
NX_EntitySetContact(*axis(2), *caisse, 0)
NX_EntitySetContact(*axis(2), *roue(2), 0)
DM_TranslateEntity(*axis(3), -4,0,-7): NX_CreatePhysicSphere(*axis(3), 0,400,0)
NX_EntitySetContact(*axis(3), *caisse, 0)
NX_EntitySetContact(*axis(3), *roue(3), 0)
;--------------------------------------------------------------
; create joints
;--------------------------------------------------------------
;
*joint = NX_CreateRevoluteJointM(*roue(0), *axis(0) , 6,0,7, 1,0,0)
*joint = NX_CreatePrismaticJoint(*axis(0), *caisse , 5,0,7, 0,1,0)
NX_CreateSpring(*axis(0), *caisse, 4,0,7 , 0.1)
*joint = NX_CreateRevoluteJointM(*roue(2), *axis(2) , -6,0,7, 1,0,0)
*joint = NX_CreatePrismaticJoint(*axis(2), *caisse , -5,0,7, 0,1,0)
NX_CreateSpring(*axis(2), *caisse, -4,0,7 , 0.1)
*joint = NX_CreateRevoluteJointM(*roue(1), *axis(1) , 6,0,-7, 1,0,0)
*joint = NX_CreatePrismaticJoint(*axis(1), *caisse , 5,0,-7, 0,1,0)
NX_CreateSpring(*axis(1), *caisse, 4,0,-7 , 0.1)
*joint = NX_CreateRevoluteJointM(*roue(3), *axis(3) , -6,0,-7, 1,0,0)
*joint = NX_CreatePrismaticJoint(*axis(3), *caisse , -5,0,-7, 0,1,0)
NX_CreateSpring(*axis(3), *caisse, -4,0,-7 , 0.1)
;---------------------------------------
; Gestion des caméras
; ---------------------------------------
*camera = DM_CreateCamera(#Null)
DM_MoveEntity(*camera, -9,25, 37)
DM_TurnEntity(*camera, 30,170, 0)
DM_CameraClsColor(*camera, 25, 25, 25)
; ---------------------------------------
; Boucle principale
; ---------------------------------------
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 WrapValue(angle.f); <- wraps a value into [0,360) fringe
;Psychophanta : http://purebasic.fr/english/viewtopic.php?t=18635
!fild dword[@f] ; <- now i have 360 into st0
!fld dword[p.v_angle]
!fprem
!fadd st1,st0
!fldz
!fcomip st1
!fcmovnbe st0,st1
!fstp st1
ProcedureReturn
!@@:dd 360
EndProcedure
Procedure CalculAngle()
DM_EntityWorld(*Caisse, @mat)
; 0 1 2 3
; 4 5 6 7
; 8 9 10 11
;12 13 14 15
Define.f c, trx, try, RADIANS
RADIANS = 57.29578
angle_y.f = ASin(mat\_31); /* Calcul de l'Angle Y */
C = Cos(angle_y);
angle_y * RADIANS ; * RADIANS;
If (Abs(C) > 0.005) ; /* Gimbal lock ? */
trx = mat\_33 / C; /* Non, donc calcul de l'angle X */
try = -mat\_32 / C;
angle_x = atan2(try, trx) * RADIANS;
trx = mat\_11 / C; /* Calcul de l'angle Z */
try = -mat\_21 / C;
angle_z = atan2(try, trx) * RADIANS;
Else ; /* Gimbal lock */
angle_x = 0; /* Angle X à 0 */
trx = mat\_22; /* Calcul de l'angle Z */
try = mat\_12;
angle_z = atan2(try, trx) * RADIANS;
EndIf
angle_x = WrapValue(angle_x); /* Modulo ;) */
angle_y = WrapValue(angle_y);
angle_z = WrapValue(angle_z);
EndProcedure
Repeat
ExamineKeyboard()
ExamineMouse()
ShowCursor_(1)
If KeyboardReleased(#PB_Key_Escape) Or WindowEvent()=#PB_Event_CloseWindow
Quit=1
EndIf
If KeyboardPushed(#PB_Key_Up)
NX_EntitySetAngularMomentum(*roue(0), 5000,0,0)
NX_EntitySetAngularMomentum(*roue(2), 5000,0,0)
EndIf
If KeyboardPushed(#PB_Key_Down)
NX_EntityAddForceAtLocalPos(*caisse, 0,0,50000, 0,2,0)
EndIf
; ---------------
; Rendu
; ---------------
; mise a jour de la physique
NX_Update()
GestionCamera()
CalculAngle()
NX_RotateEntity(*Caisse,67,0,36)
DM_BeginScene()
DM_RenderWorld()
DM_DrawText(*font,0,0,StrF(angle_x,1) + " " + StrF(angle_y,1) + " " + StrF(angle_z,1))
DM_DrawText(*font,0,20,StrF(mat\_11,1) + " " + StrF(mat\_21,1) + " " + StrF(mat\_31,1) + " " + StrF(mat\_41,1))
DM_DrawText(*font,0,40,StrF(mat\_12,1) + " " + StrF(mat\_22,1) + " " + StrF(mat\_32,1) + " " + StrF(mat\_42,1))
DM_DrawText(*font,0,60,StrF(mat\_13,1) + " " + StrF(mat\_23,1) + " " + StrF(mat\_33,1) + " " + StrF(mat\_43,1))
DM_DrawText(*font,0,80,StrF(mat\_14,1) + " " + StrF(mat\_24,1) + " " + StrF(mat\_34,1) + " " + StrF(mat\_44,1))
DM_EndScene()
Until Quit=1
NX_Exit()
DM_ClearGraphics()
End
Procedure.f CurveValue(actuelle.f, Cible.f, P.f)
;Calcule une valeur progressive allant de la valeur actuelle à la valeur cible
Define.f Delta
Delta = Cible - actuelle
If P > 1000.0 : P = 1000.0 : EndIf
ProcedureReturn (actuelle + ( Delta * P / 1000.0))
EndProcedure
Procedure GestionCamera()
Define.f Px, Py, Pz, Pv
Define.f x,y,z
Static AngleCamera.f
Pv = 25
AngleCamera = CurveValue(AngleCamera, DM_EntityYaw(*Caisse) + 90, Pv)
Px = CurveValue(DM_EntityX(*Camera), NEW_X(DM_Entityx(*Caisse), AngleCamera, 50), Pv)
Py = CurveValue(DM_EntityY(*Camera), DM_EntityY(*Caisse) + 20, Pv)
Pz = CurveValue(DM_EntityZ(*Camera), NEW_Z(DM_EntityZ(*Caisse), AngleCamera, 50), Pv)
DM_PositionEntity(*Camera, Px, Py, Pz)
DM_PointEntity(*Camera, *Caisse)
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.
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
-
- Messages : 1554
- Inscription : lun. 24/juil./2006 6:44
- Localisation : vosges (France) 47°54'39.06"N 6°20'06.39"E
Tu en est au meme point que moi. En fait cela foire dès qu'il y a combinaison des angles
qui rentrent en compte. Si je reste sur un angle a la fois, la cela fonctonne bien.
Pour ce qui est du repere, cela pourrait en effet etre une solution, mais dans les tests
généraux, comme celui du lien fourni plus haut, j'ai fait des essais sur des calculs
simple, sans réellement l'intégré dans DM3D. J'ai créé une matrice simple comme
spécifié dans le tuto, puis dans la foulé j'ai récupéré les angles sur cette meme
matrice, et la c'est toujours pareil, cela ne fonctionne pas non plus.
En fait j'ai fait plusieurs sites ou on explique super bien comment produire
une matrice de rotation par plusieurs méthodes, puis en suite de récupérer les elements, dont
les angles de rotation. Quand tu lis les tuto, cela parait limpide, et clair, seulement
quand tu met en pratique, cela ne fonctionne pas...
Maintenant je fais certainement un truc qui faut pas a un moment donné, car
dans bon nombre d'appli cela fonctionne, donc il y a forcement un hic quelque part.
qui rentrent en compte. Si je reste sur un angle a la fois, la cela fonctonne bien.
Pour ce qui est du repere, cela pourrait en effet etre une solution, mais dans les tests
généraux, comme celui du lien fourni plus haut, j'ai fait des essais sur des calculs
simple, sans réellement l'intégré dans DM3D. J'ai créé une matrice simple comme
spécifié dans le tuto, puis dans la foulé j'ai récupéré les angles sur cette meme
matrice, et la c'est toujours pareil, cela ne fonctionne pas non plus.
En fait j'ai fait plusieurs sites ou on explique super bien comment produire
une matrice de rotation par plusieurs méthodes, puis en suite de récupérer les elements, dont
les angles de rotation. Quand tu lis les tuto, cela parait limpide, et clair, seulement
quand tu met en pratique, cela ne fonctionne pas...
Maintenant je fais certainement un truc qui faut pas a un moment donné, car
dans bon nombre d'appli cela fonctionne, donc il y a forcement un hic quelque part.
Force et sagesse...
ok alors je viens de faire un exemple en utilisant les fonctions de Dx pour calculer mes matrices de rotation , et là ça semble fonctionner correctement.
J'ai pas trop tester, mais les premiers résultats sont corrects.
[EDIT]
Ok , c'est pas bon si je mets
Pis je ne suis pas sur de faire les multiplications dans le bon ordre
[EDIT2]
j'ai remplacé les multiplications par
mais c'est pas mieux
J'ai pas trop tester, mais les premiers résultats sont corrects.
[EDIT]
Ok , c'est pas bon si je mets
Code : Tout sélectionner
D3DXMatrixRotationX(@matx, #PI/2)
D3DXMatrixRotationY(@maty, #PI/2)
D3DXMatrixRotationz(@matz, #PI/3)

[EDIT2]
j'ai remplacé les multiplications par
Code : Tout sélectionner
D3DXMatrixRotationYawPitchRoll.l(@mat, #PI/4, #PI/4, 0)
Code : Tout sélectionner
;Comtois le 22/11/06
; Fichiers Include
IncludePath "..\Include\"
IncludeFile "d3dx9.pbi"
Global mat.D3DXMATRIX,mati.D3DXMATRIX,matx.D3DXMATRIX,maty.D3DXMATRIX,matz.D3DXMATRIX
Global angle_y.f,angle_x.f, angle_z.f
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 WrapValue(angle.f); <- wraps a value into [0,360) fringe
;Psychophanta : http://purebasic.fr/english/viewtopic.php?t=18635
!fild dword[@f] ; <- now i have 360 into st0
!fld dword[p.v_angle]
!fprem
!fadd st1,st0
!fldz
!fcomip st1
!fcmovnbe st0,st1
!fstp st1
ProcedureReturn
!@@:dd 360
EndProcedure
Procedure CalculAngle()
; 0 1 2 3
; 4 5 6 7
; 8 9 10 11
;12 13 14 15
Define.f c, trx, try, RADIANS
RADIANS = 57.29578
angle_y.f = ASin(mat\_31); /* Calcul de l'Angle Y */
C = Cos(angle_y);
angle_y * RADIANS ; * RADIANS;
If (Abs(C) > 0.0005) ; /* Gimbal lock ? */
trx = mat\_33 / C; /* Non, donc calcul de l'angle X */
try = -mat\_32 / C;
angle_x = atan2(try, trx) * RADIANS;
trx = mat\_11 / C; /* Calcul de l'angle Z */
try = -mat\_21 / C;
angle_z = atan2(try, trx) * RADIANS;
Else ; /* Gimbal lock */
angle_x = 0; /* Angle X à 0 */
trx = mat\_22; /* Calcul de l'angle Z */
try = mat\_12;
angle_z = atan2(try, trx) * RADIANS;
EndIf
angle_x = WrapValue(angle_x); /* Modulo ;) */
angle_y = WrapValue(angle_y);
angle_z = WrapValue(angle_z);
EndProcedure
;D3DXMatrixRotationX(@matx, #PI/2)
;D3DXMatrixRotationY(@maty, #PI/2)
;D3DXMatrixRotationz(@matz, #PI/3)
;D3DXMatrixMultiply(@mati, @matx, @maty)
;D3DXMatrixMultiply(@mat, @mati, @matz)
D3DXMatrixRotationYawPitchRoll.l(@mat, #PI/4, #PI/4, 0)
CalculAngle()
Debug StrF(angle_x,1) + " " + StrF(angle_y,1) + " " + StrF(angle_z,1)
Debug StrF(mat\_11,1) + " " + StrF(mat\_21,1) + " " +StrF(mat\_31,1) + " " +StrF(mat\_41,1)
Debug StrF(mat\_12,1) + " " + StrF(mat\_22,1) + " " +StrF(mat\_32,1) + " " +StrF(mat\_42,1)
Debug StrF(mat\_13,1) + " " + StrF(mat\_23,1) + " " +StrF(mat\_33,1) + " " +StrF(mat\_43,1)
Debug StrF(mat\_14,1) + " " + StrF(mat\_24,1) + " " +StrF(mat\_34,1) + " " +StrF(mat\_44,1)
Dernière modification par comtois le mer. 22/nov./2006 21:33, modifié 3 fois.
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.
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
bon je vais étudier ce siteplus tard, là je vais me coucher 

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.
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
j'ai bien dormi !
et je crois que j'ai trouvé la solution, à mettre à l'épreuve, je n'ai fait que quelques tests.
Bon je vais me chercher des croissants
[EDIT]
Gloups !
Si je mets tous les angles à 90° ça merdouille, mais bon c'est avec cette solution que j'obtiens les meilleurs résultats.
Faudra que je relise ça plus tard
et je crois que j'ai trouvé la solution, à mettre à l'épreuve, je n'ai fait que quelques tests.
Bon je vais me chercher des croissants

[EDIT]
Gloups !
Si je mets tous les angles à 90° ça merdouille, mais bon c'est avec cette solution que j'obtiens les meilleurs résultats.
Faudra que je relise ça plus tard
rotation matrix to euler-angles conversion
Several implementations of this have been published which give wrong answers in cases when there is more than one solution (e.g. Shoemake, Euler Angle Conversion, in Graphics Gems IV).
For definiteness, let's consider heading/pitch/roll Euler angles (or yaw/pitch/roll if you like). The subtlety occurs when the pitch is 90 degrees (or close to it): in this case any heading value could alternatively be expressed as roll, and vice-versa. So, if you are asked to decompose a rotation (matrix) in which the pitch is 90 degrees, you can choose the heading arbitrarily and then choose the roll in terms of it (or vice-versa).
Notice that in this case there is one degree of freedom in your answer, but not two! So if you have determined that the pitch is 90 degrees (or sufficiently close), you can't just throw your hands up in the air and return arbitrary numbers (e.g. zero) for both heading and roll; in general, you won't get a representation of the original matrix, which would be a bad bug in your implementation. You can return an arbitrary number for either heading or roll, but then that determines the other.
A good robust way do do this is to start by choosing the heading (or roll) using the atan2 function as usual. Note that if the pitch is 90 degrees or close to it, then you will be taking the atan2 of two numbers very close (or equal) to zero, which is unstable of course, but the worst atan2 can do is return a random angle, which is fine, and even appropriate, in this case. The next step is to create a rotation matrix representing the inverse of the heading (or roll) you have chosen, and multiply it by the original matrix on the appropriate side, effectively factoring out your chosen heading (or roll). Now you are left with a simpler matrix, from which you can robustly extract the remaining two euler angles, and when you compose them all together you are guaranteed to get back the original matrix.
Code : Tout sélectionner
;Comtois 23/11/06
; Fichiers Include
IncludePath "..\Include\"
IncludeFile "d3dx9.pbi"
Global mat.D3DXMATRIX
Global angle_y.f,angle_x.f, angle_z.f
Global x.f, y.f, z.f
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 WrapValue(angle.f); <- wraps a value into [0,360) fringe
;Psychophanta : http://purebasic.fr/english/viewtopic.php?t=18635
!fild dword[@f] ; <- now i have 360 into st0
!fld dword[p.v_angle]
!fprem
!fadd st1,st0
!fldz
!fcomip st1
!fcmovnbe st0,st1
!fstp st1
ProcedureReturn
!@@:dd 360
EndProcedure
Procedure DecomposeRollPitchYawZXYMatrix()
; http://blogs.msdn.com/MikePelton/archive/2004/10/29/249501.aspx
angle_x = ASin(-mat\_32)
test = Cos(angle_x)
angle_x * 57.29578
threshold.f = 0.001; // Hardcoded constant - burn him, he's a witch
If(test > threshold)
angle_z = Atan2(mat\_12, mat\_22) * 57.29578
angle_y = Atan2(mat\_31, mat\_33) * 57.29578
Else
zRoll = Atan2(-mat\_21, mat\_11) * 57.29578
angle_y = 0.0
EndIf
EndProcedure
x = 45 * 0.01745
y = 90 * 0.01745
z = 60 * 0.01745
D3DXMatrixRotationYawPitchRoll(@mat, y, x, z)
DecomposeRollPitchYawZXYMatrix()
Debug StrF(angle_x,1) + " " + StrF(angle_y,1) + " " + StrF(angle_z,1)
Debug "----"
Debug StrF(mat\_11,1) + " " + StrF(mat\_21,1) + " " +StrF(mat\_31,1) + " " +StrF(mat\_41,1)
Debug StrF(mat\_12,1) + " " + StrF(mat\_22,1) + " " +StrF(mat\_32,1) + " " +StrF(mat\_42,1)
Debug StrF(mat\_13,1) + " " + StrF(mat\_23,1) + " " +StrF(mat\_33,1) + " " +StrF(mat\_43,1)
Debug StrF(mat\_14,1) + " " + StrF(mat\_24,1) + " " +StrF(mat\_34,1) + " " +StrF(mat\_44,1)
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.
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
- Progi1984
- Messages : 2659
- Inscription : mar. 14/déc./2004 13:56
- Localisation : France > Rennes
- Contact :
Comtois, tout juste 6h de sommeil et il écrit un moteur 3d lol
Il dort une journée, et il nous écrit un OS :p
Il dort une journée, et il nous écrit un OS :p
Librairies & Applications : https://www.purebasic.fr/french/viewtop ... f=8&t=6220
Site Web : https://rootslabs.net
Site Web : https://rootslabs.net