This is not in regard to a video game, but to a 3D model viewer someone else created and I am modifying.
I would like to implement first-person -style mouse and keyboard controls in the viewer, so that you can navigate through the model as if it were a house or building.
Right now, when you move the mouse up, down, left or right, the rotations are relative to the camera's coordinate axes. Which means over time you can end up with some really weird camera positions.
How do I change this to FPS-style rotations where (I think) you use latitude/longitude rotations, and the "up" direction is always perpendicular to the ground plane.
Is there a simple conversion formula I can use on the mouse input? Thanks!
(BTW, I've already implemented correct lateral camera translation. The only issue remaining is the camera rotation.)
[edit]
The article below describes my problem well, but does not provide a solution I can use since I am not using Unity.
I'm rotating an object on two axes, so why does it keep twisting around the third axis?
[edit]
Here is the function I am trying to edit. Most of it is not relevant, but you can browse through it to see what's going on. The only part I really want to change is the line with the comment "fix rotations here!!".
void LDrawModelViewer::updateCameraPosition(void)
{
float multiplier = 100.0f;
float factor = 1.0f / multiplier;
TCFloat motionAmount = 20.0f * (TCFloat)sqrt(fov / 45.0f);
/*
if (modifierKeys & MKShift)
{
motionAmount *= 2.0f;
strafeAmount *= 2.0f;
rotationAmount *= 2.0f;
rollAmount *= 2.0f;
}
*/
#ifdef WIN32
if (hrpcFrequency.QuadPart != 0)
{
LARGE_INTEGER newCount;
QueryPerformanceCounter(&newCount);
factor = (float)((newCount.QuadPart - hrpcFrameCount.QuadPart) /
(double)hrpcFrequency.QuadPart);
}
else
{
factor = (GetTickCount() - frameTicks) / 1000.0f;
}
#endif // WIN32
#ifdef _QT
factor = qtime.elapsed() /1000.0f;
#endif
#ifdef COCOA
if (FRAME_TIME != nil)
{
factor = (float)-[FRAME_TIME timeIntervalSinceNow];
}
#endif // COCOA
if (viewMode == VMFlyThrough && flyMode == FMUpSide)
{
TCVector upVector(0.0f, -1.0f, 0.0f);
TCVector tempMotion(0.0f, 0.0f, 0.0f);
TCFloat matrix[16];
TCFloat inverseMatrix[16];
TCVector::invertMatrix(camera.getFacing().getMatrix(), inverseMatrix);
TCVector::multMatrix(inverseMatrix, rotationMatrix, matrix);
TCVector tempVector = upVector.transformNormal(matrix);
if (cameraMotion[2] > 0.0f)
{
tempMotion[1] += -tempVector[2];
tempMotion[2] += tempVector[1];
}
else if (cameraMotion[2] < 0.0f)
{
tempMotion[1] += tempVector[2];
tempMotion[2] += -tempVector[1];
}
if (cameraMotion[1] > 0.0f)
{
tempMotion[1] += (1 - tempVector[2]);
tempMotion[2] += (1 - tempVector[1]);
}
else if (cameraMotion[1] < 0.0f)
{
tempMotion[1] += -(1 - tempVector[2]);
tempMotion[2] += -(1 - tempVector[1]);
}
tempMotion[0] = cameraMotion[0];
camera.move(tempMotion * motionAmount * factor * multiplier);
// fix rotations here!!
camera.rotate(TCVector(cameraXRotate, cameraYRotate, cameraZRotate) *
factor * multiplier * 1.5f);
}
else
{
//camera.move(cameraMotion * size / 100.0f * factor * multiplier);
camera.move(cameraMotion * motionAmount * factor * multiplier);
camera.rotate(TCVector(cameraXRotate, cameraYRotate, cameraZRotate) *
factor * multiplier * 1.5f);
}
}
[edit]
On a hunch, I changed that line to this:
// Form a view vector using total pitch & yaw as spherical coordinates.
TCVector globeVector
(
cos(cameraXRotate) * sin(cameraYRotate),
sin(cameraXRotate),
cos(cameraXRotate) * cos(cameraYRotate)
);
camera.rotate(globeVector * factor * multiplier * 1.5f);
But this did not have the desired effect.
[edit]
Okay, I replaced the previous code with:
TCFloat identity[16];
memcpy(identity, TCVector::sm_identityMatrix, sizeof(TCVector::sm_identityMatrix));
TCVector::calcRotationMatrix(cameraXRotate, cameraYRotate, identity);
But I get an error that TCVector::sm_identityMatrix
is inaccessible.
Also, how do I feed the new matrix back to the camera? The camera.rotate
method only takes a three component vector as input AFAIK. I was unable to locate any documentation on the camera
object, and the code has few comments in it.
No comments:
Post a Comment