Rotation around 3 axis'

Alright so I have been stuck on this problem for a week now and I have decided to enter the scary world of quaternions. So I am dealing with a right handed axis system in opengl so I believe I have to make sure my matrix conversion from euler angles to quaternions has to follow a right handed conversion.

First part of my code is converting my up/down and left/right rotation controls to euler angles. The way I have my conversion set up is I first rotate around the y axis (left/right) and then I convert my x and z (up/down) rotation angles based on my y axis rotation. The 0.01745 is angle to radians conversion. theta is y angle while phi and psi are x and z angles respectively. Here is the method.


	rotVector.theta = mp_ViewState->LRangleDeg();
	rotVector.phi = mp_ViewState->UDangleDeg()*cos(rotVector.theta*0.0174532925);
	rotVector.psi =  mp_ViewState->UDangleDeg()*sin(rotVector.theta*0.0174532925);

Now onto the quaternion conversion which I think may be flawed but I followed the template on wikipedia that seemed legit as I have seen many posters use it as a source for study. Here is my first quaternion matrix that represents the x rotation matrix that I will create.


void CTEM_3D_Canvas::updateXmat(){
	
	float a = cos(rotVector.phi/2);
	float b = sin(rotVector.phi/2);
	float c = sin(rotVector.phi/2);
	float d = sin(rotVector.phi/2);
	
	rotVector.xrot[0] = a*a + b*b - c*c - d*d;
	rotVector.xrot[1] = 2*b*c - 2*a*d;
	rotVector.xrot[2] = 2*b*d + 2*a*c;
	rotVector.xrot[3] = 0;
	
	rotVector.xrot[4] = 2*b*c + 2*a*d;
	rotVector.xrot[5] = a*a - b*b + c*c - d*d;
	rotVector.xrot[6] = 2*c*d - 2*a*b;
	rotVector.xrot[7] = 0;
	
	rotVector.xrot[8] = 2*b*d - 2*a*c;
	rotVector.xrot[9] = 2*c*d + 2*a*b;
	rotVector.xrot[10] = a*a - b*b - c*c + d*d;
	rotVector.xrot[11] = 0;
	
	rotVector.xrot[12] = 0;
	rotVector.xrot[13] = 0;
	rotVector.xrot[14] = 0;
	rotVector.xrot[15] = 1;
	
}

Now the y rotation quaternion…


void CTEM_3D_Canvas::updateYmat(){
	
	float a = cos(rotVector.theta/2);
	float b = sin(rotVector.theta/2);
	float c = sin(rotVector.theta/2);
	float d = sin(rotVector.theta/2);
	rotVector.yrot[0] = a*a + b*b - c*c - d*d;
	rotVector.yrot[1] = 2*b*c - 2*a*d;
	rotVector.yrot[2] = 2*b*d + 2*a*c;
	rotVector.yrot[3] = 0;
	
	rotVector.yrot[4] = 2*b*c + 2*a*d;
	rotVector.yrot[5] = a*a - b*b + c*c - d*d;
	rotVector.yrot[6] = 2*c*d - 2*a*b;
	rotVector.yrot[7] = 0;
	
	rotVector.yrot[8] = 2*b*d - 2*a*c;
	rotVector.yrot[9] = 2*c*d + 2*a*b;
	rotVector.yrot[10] = a*a - b*b - c*c + d*d;
	rotVector.yrot[11] = 0;
	
	rotVector.yrot[12] = 0;
	rotVector.yrot[13] = 0;
	rotVector.yrot[14] = 0;
	rotVector.yrot[15] = 1;
}

And finally the z quaternion matrix…


void CTEM_3D_Canvas::updateZmat(){

	float a = cos(rotVector.psi/2);
	float b = sin(rotVector.psi/2);
	float c = sin(rotVector.psi/2);
	float d = sin(rotVector.psi/2);

	rotVector.zrot[0] = a*a + b*b - c*c - d*d;
	rotVector.zrot[1] = 2*b*c - 2*a*d;
	rotVector.zrot[2] = 2*b*d + 2*a*c;
	rotVector.zrot[3] = 0;
	
	rotVector.zrot[4] = 2*b*c + 2*a*d;
	rotVector.zrot[5] = a*a - b*b + c*c - d*d;
	rotVector.zrot[6] = 2*c*d - 2*a*b;
	rotVector.zrot[7] = 0;
	
	rotVector.zrot[8] = 2*b*d - 2*a*c;
	rotVector.zrot[9] = 2*c*d + 2*a*b;
	rotVector.zrot[10] = a*a - b*b - c*c + d*d;
	rotVector.zrot[11] = 0;
	
	rotVector.zrot[12] = 0;
	rotVector.zrot[13] = 0;
	rotVector.zrot[14] = 0;
	rotVector.zrot[15] = 1;
}

Now I have all my methods made and now I make these method calls in the my code. First I will explain. I first convert from up/down and right/left controls to euler angles. I then convert the x, y and z rotations to three different quaternion rotation matrices. I then use glMultMatrix() three times and insert the x, y and z quaternions multiplied with my projection matrix.


angleConversion();
	updateXmat();
	updateYmat();
	updateZmat();
	//Original centered object
	glPushMatrix();
	glMultMatrixf(rotVector.xrot);
	glMultMatrixf(rotVector.yrot);
	glMultMatrixf(rotVector.zrot);
	drawSquare();
	glPopMatrix();

Hopefully someone can help because I have spent a lot of time on this and I am not giving up until I solve this special problem.

I don’t think you actually stated what the specific problem you’re posting about is.

I hope your original problem wasn’t gimble lock because you’re not going to fix it this way. Quaternions are not the solution to gimble lock. You can have that with quaternions and you can not have that with matrices (or vice versa). Where it comes from is representing an aggregate rotation in terms of component rotations about different axes.

Unfortunately I am trying to solve gimbal lock so it looks like I am going about this problem incorrectly.

My problem is I would like to rotate a camera around a 3D point so that I am always looking that point. In reality I always want to be able to rotate up/down or left/right at any arbitrary axes and still focus at that point.

Gimbal lock happens when you are trying to combine three axial rotations to produce an orientation. It doesn’t matter if those rotations come from multiplying three matrices together or multiplying 3 quaternions. The problem is with doing this at all, with combining three rotations to orient something.

I would suggest spending some time with this tutorial. It’s part of a series, but should explain what quaternions are, how to use them to orient something, etc. Also, if you’re looking for camera positioning code of the type you suggest, the View Pole class from the Unofficial OpenGL SDK is a good one.

Well the tutorial is a bit confusing but what I got from it was that in order to do this problem correctly you have to do translations and rotations?

In addition to that do I have to store the previous matrix in order to translate and rotate correctly from one matrix to the next. There is a lot of stuff in there that is unclear to me. Any explanations?

Alfonse

Could you possibly explain this formula in terms of what I am trying to do? I am confused as to what C (Camera matrix) is, what R (Orientation offset) and O (current model-to-world orientation). I am not sure how they relate to my translation and rotation matrix.

//From Tutorial page
CNO = RCO
We can right-multiply both sides of this equation by the inverse transform of O.

(CNO)O-1 = (RCO)O-1
C
N
I = RCI
The I is the identity transform. From here, we can left-multiply both sides by the inverse transform of C:

C-1 (CN) = C-1*(RC)
N = C-1
(R*C)
Therefore, given an offset that is in camera space, we can generate the world-space equivalent by multiplying it between the camera and inverse camera transforms.

As I said, it’s part of a series. So when it says “camera matrix”, you’d know what that means because it was defined in previous tutorials. I’d really suggest starting from the beginning to get a solid foundation, but if you’re in a hurry, you can start from Tutorial 4. That’s where we first introduce transformations.

Unfortunately I do not have time to read chapters from a tutorial just to understand what those matrices are. I have little time to finish this project so I could use actual answers instead of just go to this web site references. Sorry if I sound irritated but I have read so many tutorials and they usually prove to not be helpful. I came to the forum for direct help so I would not have to read another fruitless tutorial.

Could you possibly explain this formula in terms of what I am trying to do?

Well, what you’re trying to do doesn’t really have to do with that. The equation you’re talking about is how I derive the math for computing an orientation change for an object relative to the orientation of the camera. You’re trying to figure out how to position and orient the camera.

The part of the tutorial that concerns you is this part. That’s where it orients an object based on changing an orientation rather three accumulated rotations.

All you need to do is use that orientation for your camera rather than for an object. The basic idea is the same either way: you keep the camera orientation, stored as a quaternion. Every frame, based on user input (or animation or however else you decide to rotate the camera), you can apply an orientation change to this orientation. The OffsetOrientation function shown in the text is where this happens.

Again, the only difference is that you’re sticking it in your camera, rather than using it for the model-to-world transform. So your first step should be to make your camera code use a position and a quaternion to define the world-to-camera transformation matrix. Once you have that working, such that you can control the camera’s orientation with the quaternion, you can then start offsetting that quaternion by another (ie: OffsetOrientation). And then you’re done.

The basic idea is the same either way: you keep the camera orientation, stored as a quaternion.

I am confused as to how I would be implementing this. I will have a 4x4 matrix that is an orientation matrix not a rotation matrix. Does that mean I would have two orientation matrices one for my up/down control and one for my left/right control?