3D Rad - Free 3D game maker - Forum

This forum is now archived!

This forum is locked, and is a read-only version. A new community-ran forum can be found at classdev.net

News:

The 3DRad community can be found at classdev.net.

Pages: [1]

Author Topic: How to 'fix' iQuaternionToEulerAngles?  (Read 715 times)

« on: March 21, 2012, 10:57:54 AM »
I guess most of you are aware of that weird thing that iQuaternionToEulerAngles does. If not, take a look at this project.
This is the script I used:
Code: [Select]
void Main()
{
   Quaternion Rot;
   iObjectOrientation(OBJ_0,Rot); //Get Rotation
   float x,y,z;
   iQuaternionToEulerAngles(Rot,x,y,z);   
   OUT_22 = y;//Set y-rotation to ValuePrint
}

Take a look at these pictures.


Seems fine.


Still going great.


Wait, what? What just happened? It went down again?


Does anybody know how to correct this and read the three rotation values separately?
Rocket Rumble, a 3D Rad puzzle game:
http://www.3drad.com/forum/index.php?topic=9896.0
« Reply #1 on: March 21, 2012, 11:36:54 AM »
Quote
Does anybody know how to correct this and read the three rotation values separately?
Sort of. But what's more important is what you plan to do with those numbers after you get them. I mean, you're not just making this script so that you can read the angle that makes the most sense to you are you? Euler angles were not made so that you can read them and understand. They are mostly for writing to them.

So, what are we trying to make? A 2D radar? A compass? Something to do with y axis rotations?

« Reply #2 on: March 21, 2012, 11:56:56 AM »
So, what are we trying to make? A 2D radar? A compass? Something to do with y axis rotations?

I didn't really ask this for a special use, just to learn. But I see your point.

Okay, uhm, let's see... How about a body for 1st person view?

EDIT: So I mean I only want the y value. The body should keep standing up straight.
Rocket Rumble, a 3D Rad puzzle game:
http://www.3drad.com/forum/index.php?topic=9896.0
« Reply #3 on: March 21, 2012, 04:15:46 PM »
I used to have that problem in 3Impact back in the day.

In my engine this is the function i use to convert quaternions to euler angles, you should be able
to port it easily enough to angel script.

hope it helps.
Code: [Select]
//convert radians to degrees
#define D3DXToDegree( radian ) ((radian) * (180.0f / D3DX_PI))

//*****************************************************************
//ODDITYENGINE - MATH - QUATERNION TO EULER ANGLES
//*****************************************************************
void iQuaternionToEulerAngles(D3DXQUATERNION* q1,D3DXVECTOR3* EulerAngles)

    //-------------------------------------------------------------
    D3DXVECTOR3 v1;
    v1.x = (float)atan2   
    ( 
        (double)(2 * q1->y * q1->w - 2 * q1->x * q1->z), 
         (double)(1 - 2 * pow(q1->y, 2) - 2 * pow(q1->z, 2))
    ); 

    v1.z = (float)asin 
    ( 
        2 * q1->x * q1->y + 2 * q1->z * q1->w 
    ); 

    v1.y = (float)atan2 
    ( 
        (double)(2 * q1->x * q1->w - 2 * q1->y * q1->z), 
        (double)(1 - 2 * pow(q1->x, 2) - 2 * pow(q1->z, 2) )
    ); 

    if (q1->x * q1->y + q1->z * q1->w == 0.5) 
    { 
        v1.x = (float)(2 * atan2((double)q1->x, (double)q1->w)); 
        v1.y = 0.0f; 
    } 

    else if (q1->x * q1->y + q1->z * q1->w == -0.5) 
    { 
        v1.x = (float)(-2 * atan2((double)q1->x,(double) q1->w)); 
        v1.y = 0.0f; 
    }
    EulerAngles->x = D3DXToDegree(v1.y);
    EulerAngles->y = D3DXToDegree(v1.x);
    EulerAngles->z = D3DXToDegree(v1.z);
    return; 
    //-------------------------------------------------------------
}   
using 3Drad 7.22

system specs:
Windows 7 Home Premium 64-bit
Intel(R) Core(TM) i5-3470 CPU @ 3.20GHz (4 CPUs), ~3.2Ghz
8 gig ram
Geforce GTX 650 1024 MB GDDR5
DirectX 11
« Reply #4 on: March 21, 2012, 04:54:29 PM »
THANKS Dave..
for some reason this always seems hard to get my head around...

--Mike
« Reply #5 on: March 21, 2012, 07:35:32 PM »
Quote from: From: 3DRAD SCRIPT REFERENCE
float iFloatSin(float)
   Return sine of specified angle.
   float = angle, in degrees

float iFloatCos(float)
   Return cosine of specified angle.
   float = angle, in degrees
+
Quote
v1.x = (float)(-2 *
atan2
((double)q1->x,(double) q1->w));
=
 :(
« Reply #6 on: March 21, 2012, 07:49:44 PM »
i think Jestermon released a math dll  http://www.3drad.com/forum/index.php?topic=4800.0 that may help out here...



if i remember correctly, it took care of angles/radians quite well...

--Mike
« Last Edit: March 21, 2012, 07:51:54 PM by Mike Hense »
« Reply #7 on: March 21, 2012, 08:19:01 PM »
Oh cool. That will work. :)
« Reply #8 on: March 21, 2012, 08:47:25 PM »
i just tried with jestermons math but it didn't seem to work correctly (see next post using the mathdll) so i just packed it into a dll and attached.

the x and y values will return from -180 to 180 where 0.0 would be facing +z. I'm not sure if it will suit your needs but I find it helpful for the things I use it for.

//probably easiest to just replace the iDllCall demo script with this and add a skinmesh with some rotation to it.
Code: [Select]
int DLLHandle = 0;


void QuaternionToEulerAngles(Quaternion q1,Vector3 &out EulerAngles)
{
   iDLLArraySet(0,q1.x);
   iDLLArraySet(1,q1.y);
   iDLLArraySet(2,q1.z);
   iDLLArraySet(3,q1.w);
   iDLLArraySet(4,0);
   iDLLCall(DLLHandle,"QuatToEulerAngles",0);
   EulerAngles.x = iDLLArrayGet(0);
   EulerAngles.y = iDLLArrayGet(1);
   EulerAngles.z = iDLLArrayGet(2);
   return;
}

void Main()
{
   if (iInitializing())
   {
      DLLHandle = iDLLLoad(".\\3DRad_res\\objects\\Script\\DLLQTE.dll");
   }
   else if (iDeinitializing())
   {
      if (DLLHandle != 0) iDLLUnload(DLLHandle);
   }
   else
   {
      if (DLLHandle != 0)
      {
         Quaternion q1;
         Vector3 v1;
         iObjectOrientation(OBJ_22,q1);
         QuaternionToEulerAngles(q1,v1);
         OUT_0 = v1.y;
      }
   }
}
« Last Edit: March 21, 2012, 09:09:23 PM by genetransfer »
using 3Drad 7.22

system specs:
Windows 7 Home Premium 64-bit
Intel(R) Core(TM) i5-3470 CPU @ 3.20GHz (4 CPUs), ~3.2Ghz
8 gig ram
Geforce GTX 650 1024 MB GDDR5
DirectX 11
« Reply #9 on: March 21, 2012, 09:11:06 PM »
...and this is using jestermon's math dll.

Code: [Select]
///****************************************************************
/// START OF RADMATH FUNCTION BLOCK
///****************************************************************
int MathDLLHandle=0;
//-----------------------------------------------------------------
//R_radians2degrees
//-----------------------------------------------------------------
float R_radians2degrees(float value)
{
   iDLLArraySet(0,value);
   iDLLCall(MathDLLHandle,"R_radians2degrees",0);
   float f = iDLLArrayGet(0);
   return f;
}
//-----------------------------------------------------------------
//R_degrees2radians
//-----------------------------------------------------------------
float R_degrees2radians(float value)
{
   iDLLArraySet(0,value);
   iDLLCall(MathDLLHandle,"R_degrees2radians",0);
   float f = iDLLArrayGet(0);
   return f;
}
//-----------------------------------------------------------------
//R_cos
//-----------------------------------------------------------------
float R_cos(float value)
{
   iDLLArraySet(0,value);
   iDLLCall(MathDLLHandle,"R_cos",0);
   float f = iDLLArrayGet(0);
   return f;
}
//-----------------------------------------------------------------
//R_sin
//-----------------------------------------------------------------
float R_sin(float value)
{
   iDLLArraySet(0,value);
   iDLLCall(MathDLLHandle,"R_sin",0);
   float f = iDLLArrayGet(0);
   return f;
}
//-----------------------------------------------------------------
//R_tan
//-----------------------------------------------------------------
float R_tan(float value)
{
   iDLLArraySet(0,value);
   iDLLCall(MathDLLHandle,"R_tan",0);
   float f = iDLLArrayGet(0);
   return f;
}
//-----------------------------------------------------------------
//R_acos
//-----------------------------------------------------------------
float R_acos(float value)
{
   iDLLArraySet(0,value);
   iDLLCall(MathDLLHandle,"R_acos",0);
   float f = iDLLArrayGet(0);
   return f;
}
//-----------------------------------------------------------------
//R_atan
//-----------------------------------------------------------------
float R_atan(float value)
{
   iDLLArraySet(0,value);
   iDLLCall(MathDLLHandle,"R_atan",0);
   float f = iDLLArrayGet(0);
   return f;
}
//-----------------------------------------------------------------
//R_asin
//-----------------------------------------------------------------
float R_asin(float value)
{
   iDLLArraySet(0,value);
   iDLLCall(MathDLLHandle,"R_asin",0);
   float f = iDLLArrayGet(0);
   return f;
}
//-----------------------------------------------------------------
//R_sinh
//-----------------------------------------------------------------
float R_sinh(float value)
{
   iDLLArraySet(0,value);
   iDLLCall(MathDLLHandle,"R_sinh",0);
   float f = iDLLArrayGet(0);
   return f;
}
//-----------------------------------------------------------------
//R_cosh
//-----------------------------------------------------------------
float R_cosh(float value)
{
   iDLLArraySet(0,value);
   iDLLCall(MathDLLHandle,"R_cosh",0);
   float f = iDLLArrayGet(0);
   return f;
}
//-----------------------------------------------------------------
//R_tanh
//-----------------------------------------------------------------
float R_tanh(float value)
{
   iDLLArraySet(0,value);
   iDLLCall(MathDLLHandle,"R_tanh",0);
   float f = iDLLArrayGet(0);
   return f;
}
//-----------------------------------------------------------------
//R_atan2
//-----------------------------------------------------------------
float R_atan2(float value1, float value2)
{
   iDLLArraySet(0,value1);
   iDLLArraySet(1,value2);
   iDLLCall(MathDLLHandle,"R_atan2",0);
   float f = iDLLArrayGet(0);
   return f;
}
//-----------------------------------------------------------------
//R_exp
//-----------------------------------------------------------------
float R_exp(float value)
{
   iDLLArraySet(0,value);
   iDLLCall(MathDLLHandle,"R_exp",0);
   float f = iDLLArrayGet(0);
   return f;
}
//-----------------------------------------------------------------
//R_log
//-----------------------------------------------------------------
float R_log(float value)
{
   iDLLArraySet(0,value);
   iDLLCall(MathDLLHandle,"R_log",0);
   float f = iDLLArrayGet(0);
   return f;
}
//-----------------------------------------------------------------
//R_log10
//-----------------------------------------------------------------
float R_log10(float value)
{
   iDLLArraySet(0,value);
   iDLLCall(MathDLLHandle,"R_log10",0);
   float f = iDLLArrayGet(0);
   return f;
}
//-----------------------------------------------------------------
//R_sqrt
//-----------------------------------------------------------------
float R_sqrt(float value)
{
   iDLLArraySet(0,value);
   iDLLCall(MathDLLHandle,"R_sqrt",0);
   float f = iDLLArrayGet(0);
   return f;
}
//-----------------------------------------------------------------
//R_pow
//-----------------------------------------------------------------
float R_pow(float value1, float value2)
{
   iDLLArraySet(0,value1);
   iDLLArraySet(1,value2);
   iDLLCall(MathDLLHandle,"R_pow",0);
   float f = iDLLArrayGet(0);
   return f;
}
//-----------------------------------------------------------------
//MathInitialize
//-----------------------------------------------------------------
void MathInitialize()
{
   MathDLLHandle = iDLLLoad(".\\3DRad_res\\objects\\Script\\RadMath.dll");
}
//-----------------------------------------------------------------
//MathDeInitialize
//-----------------------------------------------------------------
void MathDeInitialize()
{
   if (MathDLLHandle != 0)
      iDLLUnload(MathDLLHandle);
}
///****************************************************************
/// END OF RADMATH FUNCTION BLOCK
///****************************************************************

//Add your globals here
string PS;
int PRINT = OBJ_3;
//*****************************************************************
// MAIN
//*****************************************************************
void Main()
{
    //*************************************************************
    // INIT
    //*************************************************************
    if(iInitializing())
    {
       MathInitialize();
    }
    //*************************************************************
    // UPDATE
    //*************************************************************
    Quaternion Rot;
    iObjectOrientation(OBJ_0,Rot); //Get Rotation
    Vector3 v1;
    QuatToEulerAngles(Rot,v1);   
    iPrint(PS = v1.y,-10,11,PRINT);
    //*************************************************************
    // DESTROY
    //*************************************************************
    if (iDeinitializing())
    {
       MathDeInitialize();
    }
    //-------------------------------------------------------------
}


//*****************************************************************
//ODDITYENGINE - MATH - QUATERNION TO EULER ANGLES
//*****************************************************************
void QuatToEulerAngles(Quaternion q1,Vector3 &out EulerAngles)

    //-------------------------------------------------------------
    Vector3 v1;
    v1.x = R_atan2   
    ( 
        (2 * q1.y * q1.w - 2 * q1.x * q1.z), 
         (1 - 2 * R_pow(q1.y, 2) - 2 * R_pow(q1.z, 2))
    ); 

    v1.z = R_asin 
    ( 
        2 * q1.x * q1.y + 2 * q1.z * q1.w 
    ); 

    v1.y = R_atan2 
    ( 
        (2 * q1.x * q1.w - 2 * q1.y * q1.z), 
        (1 - 2 * R_pow(q1.x, 2) - 2 * R_pow(q1.z, 2) )
    ); 

    if (q1.x * q1.y + q1.z * q1.w == 0.5) 
    { 
        v1.x = (2 * R_atan2(q1.x,q1.w)); 
        v1.y = 0.0f; 
    } 

    else if (q1.x * q1.y + q1.z * q1.w == -0.5) 
    { 
        v1.x = (-2 * R_atan2(q1.x,q1.w)); 
        v1.y = 0.0f; 
    }
    EulerAngles.x = R_radians2degrees(v1.y);
    EulerAngles.y = R_radians2degrees(v1.x);
    EulerAngles.z = R_radians2degrees(v1.z);
    return; 
    //-------------------------------------------------------------
}   

« Last Edit: March 21, 2012, 09:16:46 PM by genetransfer »
using 3Drad 7.22

system specs:
Windows 7 Home Premium 64-bit
Intel(R) Core(TM) i5-3470 CPU @ 3.20GHz (4 CPUs), ~3.2Ghz
8 gig ram
Geforce GTX 650 1024 MB GDDR5
DirectX 11
« Reply #10 on: March 22, 2012, 06:31:11 AM »
I appreciate the replies guys, but this is too complicated for my young brain.  ::)

I solved the rotation thing for the body using this script.
Code: [Select]
void Main()
{
   Quaternion PlayerRot;
   iObjectOrientation(OBJ_0,PlayerRot); //Read player orientation.

   float Xrot, Yrot, Zrot;
   iQuaternionToEulerAngles(PlayerRot,Xrot,Yrot,Zrot);

   if (Xrot >= 0   && Xrot <   90) Xrot = 0;
   if (Xrot >= 90  && Xrot <  180) Xrot = 180;
   if (Xrot <= 0   && Xrot >  -90) Xrot = 0;
   if (Xrot <= -90 && Xrot > -180) Xrot = -180;

   Quaternion OnlyYRot;
   iQuaternionFromEulerAngles(OnlyYRot,Xrot,Yrot,Zrot,"xyz");

   iObjectOrientationSet(OBJ_44,OnlyYRot); //Set orientation to body.
}

I works, but I have no idea why.  ;D
Rocket Rumble, a 3D Rad puzzle game:
http://www.3drad.com/forum/index.php?topic=9896.0
Pages: [1]