C'est exceptionnel, je me lève à 7h en généralProgi1984 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éralProgi1984 a écrit :Comtois, tout juste 6h de sommeil et il écrit un moteur 3d lol
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
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, ¢re, &cSc, &scale, ¢re, &cQuat, &translate);
}
Code : Tout sélectionner
Sqr(((mat\_22*mat\_33)-(mat\_12*mat\_32*mat\_31))/mat\_11)
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;
}
}
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)
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)
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.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).
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)));
}
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