3D Movement Algorithm

Are there any programmers out there that can help me? I am writing a game that allows you to move around a 3D grid in any direction by turning to face the way you want to go (up, down, left or right) and then pressing a key to go forwards (or backwards) in that direction. I found some code online that does this but there is a problem with it - when you are looking straight up (90 degrees) and then head straight in that direction, you end up travelling at about 80 degree or so. In other words, you can never head straight up or down, only at a slope.
Here is the code… I hope someone can make some sense out of it because I can’t. I would be perfect if it wasn’t for this little problem.


float piover180 = 0.0174532925f;

if (nChar == VK_UP)
{
m_fXPos -= (float)sin(m_fHeadingpiover180) * 0.03f;
m_fYPos -= (float)sin(m_fLookUpDown
piover180) * 0.03f;
m_fZPos -= (float)cos(m_fHeading*piover180) * 0.03f;
InvalidateRect(NULL);
}

if (nChar == VK_DOWN)
{
m_fXPos += (float)sin(m_fHeadingpiover180) * 0.03f;
m_fYPos += (float)sin(m_fLookUpDown
piover180) * 0.03f;
m_fZPos += (float)cos(m_fHeading*piover180) * 0.03f;
InvalidateRect(NULL);
}

if (nChar == VK_RIGHT)
{
m_SectYRotate -= 1.0f;
m_fHeading = m_SectYRotate;
InvalidateRect(NULL);
}

if (nChar == VK_LEFT)
{
m_SectYRotate += 1.0f;
m_fHeading = m_SectYRotate;
InvalidateRect(NULL);
}

if (nChar == VK_PRIOR)
{
if (m_fLookUpDown < -90) m_fLookUpDown = -90;
m_fLookUpDown-= 1.0f;
InvalidateRect(NULL);
}

if (nChar == VK_NEXT)
{
if (m_fLookUpDown > 90) m_fLookUpDown = 90;
m_fLookUpDown+= 1.0f;
InvalidateRect(NULL);
}


If anyone can help, I’d be very thankful,
Jamie

Just learn how to use a matrix, start here.
http://web2.airmail.net/sjbaker1/matrices_can_be_your_friends.html

Oynx probably doesnt have to do any of his own matrix calculations for this simple program. The problem might simple lie in the call to gluPerspective or glFrustrum

Here is the call, do you have any idea how I can fix it?

void CDominationView::OnSize(UINT nType, int cx, int cy)
{
CView::OnSize(nType, cx, cy);

GLsizei width, height;
GLdouble aspect;

width = cx;
height = cy;

if (cy==0)
	aspect = (GLdouble)width;
else
	aspect = (GLdouble)width/(GLdouble)height;

glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45, aspect, 0.05, 40.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glDrawBuffer(GL_BACK);
//glEnable(GL_LIGHTING);
glEnable(GL_DEPTH_TEST);

}

Thanks,
Jamie

[This message has been edited by Oynx (edited 06-28-2001).]

[This message has been edited by Oynx (edited 06-28-2001).]

m_fXPos -= (float)sin(m_fHeadingpiover180) * 0.03f;
m_fYPos -= (float)sin(m_fLookUpDown
piover180) * 0.03f;
m_fZPos -= (float)cos(m_fHeading*piover180) * 0.03f;

i think your movement calcualtions are wrong, i’m using these:

mX += -2.0f * cos(mPitch / 180 * M_PI) * sin(mYaw / 180 * M_PI);
mY += 2.0f * sin(mPitch / 180 * M_PI);
mZ += 2.0f * cos(mPitch / 180 * M_PI) * cos(mYaw / 180 * M_PI);

mX, mY, mZ: position
mPitch: angle up/down
mYaw: angle left/right

i derived these formulae from the multiplication of the x-rotation-matrix (pitch) and the y-rotation-matrix (yaw), the result multiplied with the starting eye-vector (pitch = yaw = 0): (0, 0, 1) (also looking along the positive z axis)
this might be the reason for your problem

Here is a snippet of my code:

void TCamera::Move_Forwards(float frametime)
{

xpos += float(cos(xrot*piover180)sin(yrotpiover180))Move_Speed * frametime;
zpos -= float(cos(xrot
piover180)cos(yrotpiover180))Move_Speed * frametime;
ypos -= float(sin(xrot
piover180))*Move_Speed * frametime;

}

This allows you to go straight up and down although isn’t entirely correct.
Tim

@Tim Stirling:
that’s quite the same as my code, as i mentioned before Onyx’ calculations are wrong, so his results are wrong (what a conclusion g)