quaternion camera

Started by
8 comments, last by xg0blin 21 years, 3 months ago
I made my first quaternion camera today with opengl. It''s not working (so I guess technically, it isn''t "made" quite yet). I got a little article off the web that explained quaternion rotation. I will post some of the code, and hopefully someone can tell me what is screwing this up.
quaternion.h
  
#ifndef Quaternion_h
#define Quaternion_h

#include "Vector.h"

struct quaternion
{
	double x, y, z, w;
};

quaternion conjugate(quaternion);
quaternion mult(quaternion, quaternion);

#endif
  

quaternion.cpp
  
#include "Quaternion.h"

quaternion conjugate(quaternion quat)
{
	quat.x = -quat.x;
	quat.y = -quat.y;
	quat.z = -quat.z;
	return quat;
}

quaternion mult(quaternion quat1, quaternion quat2)
{
	quaternion temp;

	temp.x = quat1.x * quat2.w + quat1.w * quat2.x + 
			 quat1.y * quat2.z - quat1.z * quat2.y;
	temp.y = quat1.y * quat2.w + quat1.w * quat2.y +
			 quat1.z * quat2.x - quat1.x * quat2.z;
	temp.z = quat1.z * quat2.w + quat1.w * quat2.z +
			 quat1.x * quat2.y - quat1.y * quat2.x;
	temp.w = quat1.w * quat2.w - quat1.x * quat2.x -
			 quat1.y * quat2.y - quat1.z * quat2.z;

	return temp;
}
  

heres some of the code from my camera class. I just did the quaternion rotation inside of my rotate class.
  
void Camera::RotateCamera(double Angle, double x, double y, double z)
{
	quaternion temp, quat_view, result;

	temp.x = x * sin((Angle * PI)/360);
	temp.y = y * sin((Angle * PI)/360);
	temp.z = z * sin((Angle * PI)/360);
	temp.w = cos((Angle * PI)/360);

	quat_view.x = View.x;
	quat_view.y = View.y;
	quat_view.z = View.z;
	quat_view.w = 1;

	result = mult(mult(temp, quat_view), conjugate(temp));

	View.x = result.x;
	View.y = result.y;
	View.z = result.z;
}

void Camera::SetViewByMouse(void)
{
	int MouseX, MouseY;
	int MiddleX = SCREENWIDTH/2;
	int MiddleY = SCREENHEIGHT/2;
	Vector MouseDirection(0, 0, 0);
	static double CurrentRotationX = 0.0;

	SDL_GetMouseState(&MouseX, &MouseY);

	if((MouseX == MiddleX) && (MouseY == MiddleY))
		return;

	SDL_WarpMouse(MiddleX, MiddleY);

	MouseDirection.x = (MiddleX - MouseX)/MouseSensitivity; 
	MouseDirection.y = (MiddleY - MouseY)/MouseSensitivity;
	
	CurrentRotationX -= MouseDirection.y;

	if(CurrentRotationX >= 1.0)
		CurrentRotationX = 1.0;
	else if(CurrentRotationX <= -1.0)
		CurrentRotationX = -1.0;
	else
	{
		Vector Axis = CrossProduct(View - Position, Up);
		Axis = Normalize(Axis);

		RotateCamera(MouseDirection.x, 0, 1, 0);
		RotateCamera(MouseDirection.y, 1, 0, 0);
	}
}
  
Anybody know what is wrong, or maybe the stuff in the article I read was wrong or something?
Advertisement
well, first define "not working".

second. i don't see your draw code there, but i noticed that you aren't making any kind of quaternion to matrix function so how are you telling openGL to rotate your object?

normally you'd do something like:

glPushMatrix();
glMultMatrix(camera->quaterion->getMatrixForm());

//draw your stuff or whatever

glPopMatrix();

or you'd do something like multiply your camera's view & up vectors by the quaternion to rotate them to the proper orientation and then plug the correct values into gluLookAt(...)

-me

[edited by - Palidine on January 17, 2003 7:12:59 PM]
Well, in this demo, I just want to change my view vector, and I plan on up always staying at (0, 1, 0). What I mean by not working, is the camera doesn''t really rotate, it''ll just jerk once or twice. I''m updating with a call to
gluLookAt(Position.x, Position.y, Position.z, View.x, View.y, View.z, Up.x, Up.y, Up.z);. I just want to rotate the view vector. I figured I could just use the quaternions to do the rotate, and get the new x, y and z out of the vector that results.
Ok, I''ve tried everything. Instead of showing any more source code I''ll just explain what I''m trying to do and hopefully someone will see the flaw. Ok. I have, of course the regular Position, View, and Up vectors for my camera. I want to rotate the view vector by an angle theta around the x-axis, and let''s say an angle phi around the y-axis. Quaternions (at least as far as my understanding goes) let''s you rotate around an arbitrary normalized axis (which for my needs only needs to be the x and y axis, so (1, 0, 0) and (0, 1, 0). I want to update my camera with a call to gluLookAt(Position.x, Position.y, Position.z, View.x, View.y, View.z, Up.x, Up.y, Up.z). The way I understand it, I can turn my View vector into a quaternion by appending 0 to the end of it, so let''s just assume that my view vector is (10, 4, 9). I would append a zero turning it into
(10, 4, 9, 0). We''ll call this quaternion P. Then I make a quaternion to represent the rotation about the axis (we''ll call the axis A) that I wish to rotate about. We''ll also just assume that this axis is already normalize. So, I make this quaternion
Q = (Ax * sin(theta/2), Ay * sin(theta/2), Az * sin(theta/2), cos(theta)/2). So, from this point, I just need to take the conjugate of q, which I do Qconj = (-Qx, -Qy, -Qz, Qw). Then I multiply out Q*P*Qconj which should give me the rotated vector with a zero appended to the end of it, which I could just set my View vector to (excluding the w member of the result). The formula I''m using for multiplication is:


[a, b, c, d] * [e, f, g, h] =
[ ah + de + bg - cf,
bh + df + ce - ag,
ch + dg + af - be,
dh - ae - bf - cg ]


According to the articles and books I''ve read, this should work. I''m not trying to turn it into a matrix as I''m just trying to rotate the view vector and plug it into gluLookAt and letting that function handle it. Of course, my program isn''t really working. The source code is in the post above. Where am I screwing this up?
Ok, perhaps it''s something else. Maybe it''s my mouse movement function?. I was thinking maybe I can find the angle to rotate around by getting the vector from the mouse position to the screen center, and getting the angles from the right triangle, and get the angle from the opening. Only problem is, what vector do I rotate about? The hypotenuese of the mouse triangle? Hmm.
Believe it or not, I got it to rotate when I took out my capping function for the rotation around x. It is very jumpy, and when you want to just rotate around y, it jumps up on the x, and down and what not. If I comment out the rotation around x, the y rotation works perfectly. Hmm. Gotta cap it though, so this is now the problem.
Nevermind, I got it.
xg0blin, can you explain how you fixed your code? I''m having similar problems, and I''d like to see what you did.

Thanks

yckx
If you give me an email addy or something, I can mail it to you. You''ll need SDL, fmod, and opengl.
jon@joncapps.com

Thanks.

yckx

This topic is closed to new replies.

Advertisement