void GLCamera::setPerspective () {
GLfloat mat[16];
rotation.createMatrix(mat);
glMultMatrixf (mat);
glTranslatef (campos.x, campos.y, campos.z);
}
void GLCamera::rotate (float x, float y, float z) {
GLQuaternion qYaw, qPitch;
qPitch.createFromAngle (1.0f, 0.0f, 0.0f, y);
qYaw.createFromAngle (0.0f, 1.0f, 0.0f, x);
rotation = qYaw * rotation;
rotation = qPitch * rotation;
}
void GLCamera::translate (float x, float y, float z) {
campos += rotation * Vector3d (x,y,z) * 0.1f;
}
Vector3d GLQuaternion::operator* (const Vector3d v) const {
Vector3d vn (v);
vn.normalize ();
GLQuaternion vq, rq;
vq.m_x = vn.x;
vq.m_y = vn.y;
vq.m_z = vn.z;
vq.m_w = 0.0f;
rq = vq * conjugate ();
rq = *this * rq;
return (Vector3d (rq.m_x, rq.m_y, rq.m_z));
}
GLQuaternion GLQuaternion::conjugate () const {
return (GLQuaternion (-m_x, -m_y, -m_z, m_w));
}
Quaternion camera translations
Hi,
I've been having some trouble translating my quaternion camera for some time now, and I was wondering if you could help me out. I know I don't fully understand the math behind matrices and quaternions and whatnot, but am learning quite fast.
I'm making a free-rotating camera, which allows free navigation using the mouse and it's all three buttons, but I can't find any help on translating the camera when the camera orientation is totally free. It seems as if the vector for the translations is for some reason mirrored over every global axis.
Here are the relevant parts of the code:
Everyone just seems to be making a 3d-shooter, and tutorials for those seem to be no good when making a true 3d-camera.
Couple o' things:
1. You didn't post the code that (presumably) makes use of the GLCamera::translate() function to change the position of the ship, so it's a little hard to say why you're not getting the correct results. Can you post that code?
2. Why are you normalizing the input vector in the quaternion-vector multiplication function? I'm not sure if that's the cause of the problem, but in any event it's not typical; the length of a vector should be invariant under rotation.
3. IMO overloading operator*() as 'quaternion-vector multiplication' is a bad idea - that's something you might revisit after you get things working.
1. You didn't post the code that (presumably) makes use of the GLCamera::translate() function to change the position of the ship, so it's a little hard to say why you're not getting the correct results. Can you post that code?
2. Why are you normalizing the input vector in the quaternion-vector multiplication function? I'm not sure if that's the cause of the problem, but in any event it's not typical; the length of a vector should be invariant under rotation.
3. IMO overloading operator*() as 'quaternion-vector multiplication' is a bad idea - that's something you might revisit after you get things working.
1.
I am aware there is some unwanted spaghetti in the code... (Main calling gfx calling camera..), but I just haven't gotten to rewrite them... =P
2. The input vector was normalized in the tutorial x, which I used to write the basics of the camera and quaternion classes. It seemed a bit odd, I must admit.
3. operator* is also overloaded as quaternion multiplication. At the moment I consider it a nice feat to be able to use * to multiply a vector with a quaternion.
static void main_loop () { SDL_Event event; while (1) { while (SDL_PollEvent (&event)) { switch (event.type) { case SDL_MOUSEMOTION: gfx.putMouseAt (event.motion.x, event.motion.y); if (SDL_GetMouseState(NULL,NULL)&SDL_BUTTON(SDL_BUTTON_LEFT)) { gfx.rotate (event.motion.xrel, event.motion.yrel); } else if (SDL_GetMouseState(NULL,NULL)&SDL_BUTTON(SDL_BUTTON_RIGHT)) { gfx.move (float(event.motion.xrel)/100, -float(event.motion.yrel)/100, 0.0f); } break; case SDL_MOUSEBUTTONDOWN: switch (event.button.button) { case SDL_BUTTON_WHEELDOWN: gfx.moveOut (); break; case SDL_BUTTON_WHEELUP: gfx.moveIn (); break; } break; } } usleep (2); }}void Gfx::rotate (float x, float y) { camera.rotate (x, y, 0.0f);}void Gfx::move (float x, float y, float z) { camera.translate (x, y, z);}
I am aware there is some unwanted spaghetti in the code... (Main calling gfx calling camera..), but I just haven't gotten to rewrite them... =P
2. The input vector was normalized in the tutorial x, which I used to write the basics of the camera and quaternion classes. It seemed a bit odd, I must admit.
3. operator* is also overloaded as quaternion multiplication. At the moment I consider it a nice feat to be able to use * to multiply a vector with a quaternion.
Quote:Original post by RakshasaI see several places there where the camera's position is adjusted. Which of them isn't working?
1.
*** Source Snippet Removed ***
Also, I don't see the moveIn() and moveOut() functions anywhere, so you might post those as well.
Sigh, I just keep forgetting everything...
All the move functions work incorrectly after the camera has been rotated, but work correctly if I translate from the original position.
It's as if the rotated camera translation is applied mirrored over every global axis or something.
void moveIn () { camera.translate (0.0f, 0.0f, -0.1f); } void moveOut () { camera.translate (0.0f, 0.0f, 0.1f); }
All the move functions work incorrectly after the camera has been rotated, but work correctly if I translate from the original position.
It's as if the rotated camera translation is applied mirrored over every global axis or something.
There are still a lot of places that the error could be (for example, in the quat-to-matrix conversion code), but here's another thing that I noticed:
First of all, the term 'perspective' in 3D graphics generally refers to a type of projection; a name such as setViewTransform() might be more appropriate here.
Now, assuming this function is intended to set the view transform, the operations are in the right order but the transforms themselves are incorrect. Each component transform needs to be inverted, like this:
Note that making the above change still might not fix the problem (the bits of code you haven't posted might still be in error), but it should be a step in the right direction.
void GLCamera::setPerspective () { GLfloat mat[16]; rotation.createMatrix(mat); glMultMatrixf (mat); glTranslatef (campos.x, campos.y, campos.z);}
This is almost certainly wrong.First of all, the term 'perspective' in 3D graphics generally refers to a type of projection; a name such as setViewTransform() might be more appropriate here.
Now, assuming this function is intended to set the view transform, the operations are in the right order but the transforms themselves are incorrect. Each component transform needs to be inverted, like this:
void GLCamera::setPerspective () { GLfloat mat[16]; rotation.conjugate().createMatrix(mat); glMultMatrixf (mat); glTranslatef (-campos.x, -campos.y, -campos.z);}
Once you make this change, you may find that your key mappings for changing the ship's rotation are 'backwards'. This is because they're probably already backwards to compensate for the incorrect view transform; just reverse them and you should be ok.Note that making the above change still might not fix the problem (the bits of code you haven't posted might still be in error), but it should be a step in the right direction.
Thank you jyk, you've been most helpful. I changed the function to setViewTransform as you suggested, and after I inverted all the transform attributes, the camera transformation started working correctly. Now there is a slight new problem; When the Yaw is ±90 degrees, pitch becomes roll.
EDIT: I fixed the rotation by rewriting the rotation function like this:
Thank you again, jyk. Now the camera works just as intended.
[Edited by - Rakshasa on March 12, 2007 2:20:25 AM]
EDIT: I fixed the rotation by rewriting the rotation function like this:
void GLCamera::rotate (float x, float y, float z) { yaw += x; pitch += y; if (yaw > 360) yaw -= 360; else if (yaw < -360) yaw += 360; if (pitch > 360) pitch -= 360; else if (pitch < -360) pitch += 360; GLQuaternion qYaw, qPitch; qPitch.createFromAngle (1.0f, 0.0f, 0.0f, pitch); qYaw.createFromAngle (0.0f, 1.0f, 0.0f, yaw); rotation = qYaw * qPitch;}
Thank you again, jyk. Now the camera works just as intended.
[Edited by - Rakshasa on March 12, 2007 2:20:25 AM]
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement