Jump to content
  • Advertisement
Sign in to follow this  
HobbyDude

3D rotation question

This topic is 2575 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello! I have a question about rotations. Here's my code:

// Move based on player coordinates...
xBleh = object.xLoc - player.xLoc;
yBleh = object.yLoc - player.yLoc;
zBleh = object.zLoc - player.zLoc;
// Rotate view along 'x' axis...
// ...
xTemp = xBleh*cos(player.fRotVal) - zBleh*sin(player.fRotVal);
zTemp = xBleh*sin(player.fRotVal) + zBleh*cos(player.fRotVal);
// Rotate view along 'y' axis...
// ...
yTemp = yBleh*cos(player.fYawVal) - zTemp*sin(player.fYawVal);
zTemp = yBleh*sin(player.fYawVal) + zTemp*cos(player.fYawVal);


What I'm trying to do is move 'rock' sprites around in a 3D space where it looks like I'm flying around in an asteroid field. fRotVal is the player's left/right 'rotation' value (rotation along player's 'y' axis), and fYawVal is the player's up/down 'yaw' value (rotation along the player's 'x' axis). The above code works OK, but the rotations look like they're always happening around the environment's 'y' axis. Similar to riding a merry-go-round, if I look off the side of the merry-go-round things look like they're moving from left to right. But if I look up while on the merry-go-round, things look like they're spinning in a circle. I'd rather my view look like I'm flying a ship, where the axis of rotation is based on the player's orientation in outer space... Can one of you help me modify the above code so it appears the asteroids wipe left/right or up/down no matter what orientation I'm at?

PS: I'm definitely open to ideas if there's a better way to do this, I'm using 'yaw' and 'rotate' just because that's what I got to work first. ;)

Thanks in advance for the help!

Share this post


Link to post
Share on other sites
Advertisement
Search the forum archives for '6dof movement' or '6dof motion'.

Share this post


Link to post
Share on other sites
What you want is to keep a matrix to represent the orientation. Then, to pitch up/down grab the right vector from the matrix(the first column) and perform arbitrary axis rotation on the matrix around the right vector. For yaw, use the up from the matrix(the 2nd column) and use the matrix Z axis for the roll. Euler angles will not get you the desired motion...

You would also need to re-orthaganlize the matrix every frame or every few frames so accumulated error doesn't make you scene/model blow up. Do this by grabbing the right and forward vectors, take the cross product and store result in the up vector column in the matrix. The take the side and up vectors and cross and store for the forward. Make sure the vectors are normalized as well...

Share this post


Link to post
Share on other sites
Dang, I just can't wrap my head around this stuff... I'm medicated for adhd so I have a hard time inferring what's being described when all of the steps aren't there. All of the search results for '6dof' I've found use some form of library function rather than stepping out the math involved in the calculations I'm trying to perform. Can any of you direct me to where I can find a step-by-step tutorial on this?

I hope I don't sound harsh or anything as that's not my intention, I carry a lot of respect for you! It's just that I have the grammar etiquette of a musk ox.

Thanks!

Share this post


Link to post
Share on other sites
BuffaloJ gave a good step-by-step description. There are other ways it can be done, but the way he described should work.

If there are still parts that are unclear, perhaps you could narrow down your question a bit. Which part of the process in particular are you unsure of?

Share this post


Link to post
Share on other sites
I'm not sure where to start, jyk. I read BuffaloJ's response (thanks BuffaloJ!), but I don't really understand the math (or terminology - re-orthaganlize?) behind it. Maybe I shouldn't get in this deep this quick...

I guess what I don't understand is how to rotate around an arbitrary axis... I know I need an axis of rotation, and I can get that in the form of a vector (it would be the direction the player is facing). I just don' t know how to utilize the axis of rotation. You can see that my code is pretty basic in that it can rotate around the 'x' or 'y' axis and that's about it, and there's no way that I've found to code an arbitrary axis of rotation into it. I hope you can figure out from my post the point where I need help, because I don't really know where to start.

Thanks!

Share this post


Link to post
Share on other sites

I guess what I don't understand is how to rotate around an arbitrary axis... I know I need an axis of rotation, and I can get that in the form of a vector (it would be the direction the player is facing). I just don' t know how to utilize the axis of rotation. You can see that my code is pretty basic in that it can rotate around the 'x' or 'y' axis and that's about it, and there's no way that I've found to code an arbitrary axis of rotation into it. I hope you can figure out from my post the point where I need help, because I don't really know where to start.

You can actually do it without the need for an arbitrary axis-angle rotation (by reversing the multiplication order). Nevertheless, you'll definitely need to know at least the basics of matrix and vector math in order to implement something like this from scratch.

If a book is an option for you, I recommend '3D Math Primer for Graphics and Game Development' as a starting point. (I know there are some other good introductory books available, but that's the one I'm most familiar with.)

Share this post


Link to post
Share on other sites
Thanks for the info jyk, I'll check that out. It looks like a very informative book! I also found an article at 'cprogramming.com' that lines out matrix math and quaternions pretty well. I know enough vector math to be dangerous, but I know hardly anything at all about matrix math. I'll go check out those sources and come back if I still can't figure it out.

Thanks for the info, and thanks for your patience! :)

Share this post


Link to post
Share on other sites
6 degrees of freedom camera? Remember struggling on that one a while ago. (EDIT: sorry if this doesn't answer your question but I also have a problem with paying attention to things :P )

Here's my (probably not very clean) code for it:

[EDIT: added explanatory comments]


void CameraClass::Move(BYTE (*pKeys)[256], DIMOUSESTATE2 * pMouseState, float KeyboardSensitivity, float MouseWheelSensitivity, float MouseXYSensitivity)
{
//This is where I turn DirectInput keyboard and mouse states into camera movements, where BF = back forwards, UD is up downright, LR is left right.
float DeltaLR = (float)( ( (*pKeys)[DIK_A] & 0x80 ) - ( (*pKeys)[DIK_D] & 0x80 ) );
float DeltaBF = (float)( ( (*pKeys)[DIK_W] & 0x80 ) - ( (*pKeys)[DIK_S] & 0x80 ) );
float DeltaUD = (float)(pMouseState->lZ);
float DeltaYaw = (float)pMouseState->lX;
float DeltaPitch = (float)pMouseState->lY;
float DeltaRoll = (float)( ( (*pKeys)[DIK_Q] & 0x80 ) - ( (*pKeys)[DIK_E] & 0x80 ) );

//Checking the camera actually moves. If not return.
if( DeltaLR == 0.0f && DeltaBF == 0.0f && DeltaUD == 0.0f && DeltaYaw == 0.0f && DeltaPitch == 0.0f && DeltaRoll == 0.0f){ return; }

//Applying custom sensitivity to the controls
DeltaYaw = MouseXYSensitivity * DeltaYaw; DeltaPitch = MouseXYSensitivity * DeltaPitch; DeltaRoll = KeyboardSensitivity * DeltaRoll;
DeltaLR = KeyboardSensitivity*DeltaLR; DeltaBF = KeyboardSensitivity*DeltaBF; DeltaUD = MouseWheelSensitivity*DeltaUD;

//Just putting my camera info into d3d vectors
D3DXVECTOR3 Look((pCameraInfo->CamLookVector)[0], (pCameraInfo->CamLookVector)[1], (pCameraInfo->CamLookVector)[2]);
D3DXVECTOR3 Up((pCameraInfo->CamUpVector)[0], (pCameraInfo->CamUpVector)[1], (pCameraInfo->CamUpVector)[2]);
D3DXVECTOR3 Right((pCameraInfo->CamRightVector)[0], (pCameraInfo->CamRightVector)[1], (pCameraInfo->CamRightVector)[2]);

//Building the rotation matrices
D3DXMATRIX RotationAroundLook, RotationAroundUp, RotationAroundRight;
D3DXMatrixRotationAxis(&RotationAroundLook, &Look, DeltaRoll);
D3DXMatrixRotationAxis(&RotationAroundUp, &Up, DeltaYaw);
D3DXMatrixRotationAxis(&RotationAroundRight, &Right, DeltaPitch);

//Applying the rotation matrices
D3DXVec3TransformCoord(&Look, &Look, &(RotationAroundRight * RotationAroundUp) );
D3DXVec3TransformCoord(&Up, &Up, &(RotationAroundRight * RotationAroundLook) );
D3DXVec3TransformCoord(&Right, &Right, &(RotationAroundUp * RotationAroundLook) );

//Re-orthogonalising the camera vectors due to them getting deformed over time
D3DXVec3Cross(&Right, &Up, &Look );
D3DXVec3Cross(&Up, &Look, &Right);
D3DXVec3Normalize(&Look, &Look);
D3DXVec3Normalize(&Up, &Up);
D3DXVec3Normalize(&Right, &Right);

//Dealing with translation
D3DXVECTOR3 Position( (pCameraInfo->CamPos)[0], (pCameraInfo->CamPos)[1], (pCameraInfo->CamPos)[2] );
Position += -DeltaLR*Right + DeltaBF*Look + DeltaUD*Up;

//Putting the updated vectors back into my camera info struct
pCameraInfo->CamLookVector = D3DXVECTOR4(Look.x, Look.y, Look.z, 0.0f);
pCameraInfo->CamUpVector = D3DXVECTOR4(Up.x, Up.y, Up.z, 0.0f);
pCameraInfo->CamRightVector = D3DXVECTOR4(Right.x, Right.y, Right.z, 0.0f);
pCameraInfo->CamPos = D3DXVECTOR4(Position.x, Position.y, Position.z, 0.0f);
}


Hope that helps. Feel free to use it. I'll be glad to answer any questions.

Share this post


Link to post
Share on other sites
I'm baaack... I'm still trying to get this working, I read up on some matrix math and played around with some of the basics. Now I'm trying to apply BuffaloJ's idea (looks like forsandifs uses the same method) and can't get it to update my ship's axis vector... If I push the 'up' key, the ship rotates up slightly and then jumps back to its original orientation when I let go of the 'up' key. Same thing if I push 'down', 'left', and 'right', the ship's view moves slightly in that direction and then jumps back to original orientation when I let go of that key. Can you look at this and see what I'm doing incorrectly? Feel free to educate me if you find something I did heinously incorrect, I'm open to learning!


// BuffaloJ:
// What you want is to keep a matrix to represent
// the orientation. Then, to pitch up/down grab the
// right vector from the matrix(the first column)
// and perform arbitrary axis rotation on the matrix
// around the right vector. My matrix is maRC (maRowCol)

// Pitch (1st column of ship axis matrix)...
vX = ma11;
vY = ma21;
vZ = ma31;
y11 = ((1-cos(cAnglX))*vX*vX + cos(cAnglX));
y12 = ((1-cos(cAnglX))*vX*vY - sin(cAnglX)*vZ);
y13 = ((1-cos(cAnglX))*vX*vZ + sin(cAnglX)*vY);
y21 = ((1-cos(cAnglX))*vX*vY + sin(cAnglX)*vZ);
y22 = ((1-cos(cAnglX))*vY*vY + cos(cAnglX));
y23 = ((1-cos(cAnglX))*vY*vZ - sin(cAnglX)*vX);
y31 = ((1-cos(cAnglX))*vX*vZ - sin(cAnglX)*vY);
y32 = ((1-cos(cAnglX))*vY*vZ + sin(cAnglX)*vX);
y33 = ((1-cos(cAnglX))*vZ*vZ + cos(cAnglX));

// For yaw, use the up from the matrix(the 2nd column)
// and use the matrix Z axis for the roll. Euler
// angles will not get you the desired motion...

// Yaw (2nd column of ship axis matrix)...
vX = ma12;
vY = ma22;
vZ = ma32;
x11 = ((1-cos(cAnglY))*vX*vX + cos(cAnglY));
x12 = ((1-cos(cAnglY))*vX*vY - sin(cAnglY)*vZ);
x13 = ((1-cos(cAnglY))*vX*vZ + sin(cAnglY)*vY);
x21 = ((1-cos(cAnglY))*vX*vY + sin(cAnglY)*vZ);
x22 = ((1-cos(cAnglY))*vY*vY + cos(cAnglY));
x23 = ((1-cos(cAnglY))*vY*vZ - sin(cAnglY)*vX);
x31 = ((1-cos(cAnglY))*vX*vZ - sin(cAnglY)*vY);
x32 = ((1-cos(cAnglY))*vY*vZ + sin(cAnglY)*vX);
x33 = ((1-cos(cAnglY))*vZ*vZ + cos(cAnglY));

m11 = x11*y11+x12*y21+x13*y31;
m12 = x11*y12+x12*y22+x13*y32;
m13 = x11*y13+x12*y23+x13*y33;
m21 = x21*y11+x22*y21+x23*y31;
m22 = x21*y12+x22*y22+x23*y32;
m23 = x21*y13+x22*y23+x23*y33;
m31 = x31*y11+x32*y21+x33*y31;
m32 = x31*y12+x32*y22+x33*y32;
m33 = x31*y13+x32*y23+x33*y33;

// Rotation has been applied to last axis matrix, zero this out for the next frame.
// We'll update the ship's rotation axis further down.
cAnglX = 0.0;
cAnglY = 0.0;

// You would also need to re-orthaganlize the matrix every
// frame or every few frames so accumulated error doesn't
// make you scene/model blow up. Do this by grabbing the
// right and forward vectors, take the cross product and
// store result in the up vector column in the matrix. The
// take the side and up vectors and cross and store for the
// forward. Make sure the vectors are normalized as well...
// X = V x W = (X1, X2, X3) = (V2W3 - V3W2, V3W1 - V1W3, V1W2 - V2W1)
// X = R x F = (X1, X2, X3) = (R2F3 - R3F2, R3F1 - R1F3, R1F2 - R2F1)
// Right = mx1
// Forward = mx3

var rfx, rfy, rfz, rfMag;
var rux, ruy, ruz, ruMag;
var rx, ry, rz, rMag;

// Cross-product of right/forward vectors (store in 'up')...
rfx = m21*m33 - m31*m23;
rfy = m31*m13 - m11*m33;
rfz = m11*m23 - m21*m13;
rfMag = sqrt(rfx*rfx + rfy*rfy + rfz*rfz);
rfx = rfx/rfMag;
rfy = rfy/rfMag;
rfz = rfz/rfMag;

// Cross-product of right/up vectors (store in 'forward')...
rux = m21*m32 - m31*m22;
ruy = m31*m12 - m11*m32;
ruz = m11*m22 - m21*m12;
ruMag = sqrt(rux*rux + ruy*ruy + ruz*ruz);
rux = rux/ruMag;
ruy = ruy/ruMag;
ruz = ruz/ruMag;

// Normalize 'x' vector...
rMag = sqrt(m11*m11 + m21*m21 + m31*m31);
rx = m11/rMag;
ry = m21/rMag;
rz = m31/rMag;

// Store it all (update ship axis orientation for next frame)...
ma11 = rx;
ma12 = rfx;
ma13 = rux;
ma21 = ry;
ma22 = rfy;
ma23 = ruy;
ma31 = rz;
ma32 = rfz;
ma33 = ruz;

...

// Apply Pitch/yaw (xTemp/yTemp/zTemp is an object's x/y/z location in the game world)...
tX = xTemp;
tY = yTemp;
tZ = zTemp;
xTemp = tX*m11 + tY*m12 + tZ*m13;
yTemp = tX*m21 + tY*m22 + tZ*m23;
zTemp = tX*m31 + tY*m32 + tZ*m33;



Sorry it's all laid out in a very inefficient manner, I'm keeping this as readable as possible so I can fully understand how it works. Thanks in advance for the help. I'm REALLY excited about getting this to work (and actually understanding WHY it works too)!

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!