Thread: Model orientations in 3D

Threaded View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607

    Model orientations in 3D

    I'm having a lot of problems getting my models to act correctly in 3D. Currently I'm using Euler angles via axis angle rotations.

    The class for the camera works well and uses the standard up,right and look vector system.

    To pitch I rotate about the right vector.
    To yaw I rotate about the up vector.
    To roll I rotate about the look vector.

    This all works perfect for the camera and there is no gimbal lock or veering between angles (as angle axes begin to map onto one another). This tends to produce a bobbing sensation as the angles map onto one another and thus you lose a degree of freedom.

    Now I took the camera class and used it for the COrient3D class. I figured hey it works for the camera why wouldn't it for the models? Boy was I way off.

    Here are the problems:

    • Models act fine until they reach negative pitch at which point the look vector and nose of the model do not line up.
    • As you approach the +90 to -90 the effects of this can be seen quite clearly as your model begins to waiver about and no longer follow the look vector.
    • If you yaw while in a positive or negative pitch it works fine until yaw reaches a certain point and then the vectors go haywire.
    • The ship nose should point straight down the +z axis of the look vector, but the ship movement begins to be completely different from the direction it is pointing.


    Now if I absolutely cannot do this type of game using euler angles then I will switch to quaternions, but I think something else is wrong.

    Here is some of the code:

    Code:
    COrient3D::COrient3D()
    {
      m_vecRight=D3DXVECTOR3(1.0f,0.0f,0.0f);
      m_vecUp=D3DXVECTOR3(0.0f,1.0f,0.0f);
      m_vecLook=D3DXVECTOR3(0.0f,0.0f,1.0f);
      m_vecPos=D3DXVECTOR3(0.0f,0.0f,0.0f);
      m_iObjType=OBJECT_AIR;
      m_fYaw=0.0f;
      m_fRoll=0.0f;
      m_fPitch=0.0f;
    }
    
    void COrient3D::Walk(float fUnits)
    {
      if (m_iObjType==OBJECT_GND)
         m_vecPos+=D3DXVECTOR3(m_vecLook.x,0.0f,m_vecLook.z)*fUnits;
    
      if (m_iObjType==OBJECT_AIR)
         m_vecPos+=m_vecLook*fUnits;
    }
    
    void COrient3D::Roll(float fAngle)
    {
      m_fRoll+=fAngle;
      
      D3DXMATRIX T;
      D3DXMatrixRotationAxis(&T,&m_vecLook,fAngle);
    
      D3DXVec3TransformCoord(&m_vecRight,&m_vecRight,&T);
      D3DXVec3TransformCoord(&m_vecUp,&m_vecUp,&T);
    
    }
    
    void COrient3D::Pitch(float fAngle)
    {
      m_fPitch+=fAngle;
      
      D3DXMATRIX T;
      D3DXMatrixRotationAxis(&T,&m_vecRight,fAngle);
    
      D3DXVec3TransformCoord(&m_vecUp,&m_vecUp,&T);
      D3DXVec3TransformCoord(&m_vecLook,&m_vecLook,&T);
    
    }
    
    void COrient3D::Yaw(float fAngle)
    {
      m_fYaw+=fAngle;
      
    
      D3DXMATRIX T;
    
      if (m_iObjType==OBJECT_GND) D3DXMatrixRotationY(&T,fAngle);
      if (m_iObjType==OBJECT_AIR) D3DXMatrixRotationAxis(&T,&m_vecUp,fAngle);
    
      D3DXVec3TransformCoord(&m_vecRight,&m_vecRight,&T);
      D3DXVec3TransformCoord(&m_vecLook,&m_vecLook,&T);
    
    }
    
    void COrient3D::GetRotMatrix(D3DXMATRIX *outMatrix)
    {
      D3DXVec3Normalize(&m_vecLook,&m_vecLook);
      
      D3DXVec3Cross(&m_vecUp,&m_vecLook,&m_vecRight);
      D3DXVec3Normalize(&m_vecRight,&m_vecRight);
    
      D3DXVec3Cross(&m_vecRight,&m_vecUp,&m_vecLook);
      D3DXVec3Normalize(&m_vecLook,&m_vecLook);
    
      D3DXVECTOR3 vecPos=m_vecPos;
      
      float x=D3DXVec3Dot(&m_vecRight,&vecPos);
      float y=D3DXVec3Dot(&m_vecUp,&vecPos);
      float z=D3DXVec3Dot(&m_vecLook,&vecPos);
    
      (*outMatrix)(0,0)=m_vecRight.x;
      (*outMatrix)(0,1)=m_vecUp.x;
      (*outMatrix)(0,2)=m_vecLook.x;
      (*outMatrix)(0,3)=0.0f;
    
      (*outMatrix)(1,0)=m_vecRight.y;
      (*outMatrix)(1,1)=m_vecUp.y;
      (*outMatrix)(1,2)=m_vecLook.y;
      (*outMatrix)(1,3)=0.0f;
    
      (*outMatrix)(2,0)=m_vecRight.z;
      (*outMatrix)(2,1)=m_vecUp.z;
      (*outMatrix)(2,2)=m_vecLook.z;
      (*outMatrix)(2,3)=0.0f;
    
      (*outMatrix)(3,0)=0.0f;
      (*outMatrix)(3,1)=0.0f;
      (*outMatrix)(3,2)=0.0f;
      (*outMatrix)(3,3)=1.0f;
    }
    What I've done here is take the GetViewMatrix() function from CCamera and used it to create the final rotation matrix for the object. I cannot do a D3DXMatrixRotationYawPitchRoll() because that suffers from gimbal lock which would effectively 'undo' all my axis angle rotations.

    You may notice the translation has been taken out of this matrix. It is done at a later time just in case I may want to scale the object prior to translation and I didn't think COrient3D should care about scale.

    This code works fine for the camera but is completely backwards for the object. After negating certain vectors you can get the object to fly correctly, but the issues I mentioned above pop up quickly.

    I tried code to rotate the object to always face down the positive Z axis of the look vector, but it did not change the object orientation leading me to believe it is already in this orientation.

    Please help me figure this out. These orientations are driving me nuts.
    Last edited by VirtualAce; 10-31-2006 at 04:47 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. 3d model with lighting effects
    By redacted user in forum Tech Board
    Replies: 2
    Last Post: 10-10-2008, 05:31 PM
  2. 3d Model file format
    By glo in forum Game Programming
    Replies: 4
    Last Post: 09-15-2008, 04:33 PM
  3. Help with file reading/dynamic memory allocation
    By Quasar in forum C++ Programming
    Replies: 4
    Last Post: 05-17-2004, 03:36 PM
  4. I'm completely stuck!
    By tek in forum C++ Programming
    Replies: 0
    Last Post: 08-23-2003, 06:43 PM
  5. 3D starfield
    By VirtualAce in forum Game Programming
    Replies: 6
    Last Post: 06-26-2003, 12:40 PM