Quaternion Problems.

Started by
2 comments, last by yacwroy 14 years, 7 months ago
I am working on a Quaternion based camera class, and all has been well until now... Basically, I am using the mouse to control the camera's Yaw & Pitch. When i start the program, I am looking at a cube and I can Yaw & Pitch the camera correctly, but when i go 1 side to the left, look at the cube, and try to pitch the camera(mouse up & down) it seems like it is rolling. Then if i go to the back of the cube and pitch it, it is correct. As i go from front to side and pith the camera, it rolls more and pitches less until it is aligned with the side of the cube, and it does nothing but roll. Here is some code. Camera.cpp

#include "Camera.hpp"

#include <math.h>

Camera::Camera()
{
    FovY = 3.141592f * 0.5f;
    AspectRatio = 0.0f;
    ZNear = 0.1f;
    ZFar = 100.0f;
    
    Position = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
    XAxis = D3DXVECTOR3(1.0f, 0.0f, 0.0f);
    YAxis = D3DXVECTOR3(0.0f, 1.0f, 0.0f);
    ZAxis = D3DXVECTOR3(0.0f, 0.0f, 1.0f);

    D3DXQuaternionIdentity(&Orientation);
    D3DXMatrixIdentity(&View);
    D3DXMatrixIdentity(&Projection);

	SetView(Position, XAxis, YAxis, ZAxis);
	SetProjection(FovY, AspectRatio, ZNear, ZFar);
};

void Camera::SetView(const D3DXVECTOR3& Position, const D3DXVECTOR3& XAxis, const D3DXVECTOR3& YAxis, const D3DXVECTOR3& ZAxis)
{
	View(0, 0) = XAxis.x;
	View(0, 1) = YAxis.x;
	View(0, 2) = ZAxis.x;
	View(0, 3) = 0;

	View(1, 0) = XAxis.y;
	View(1, 1) = YAxis.y;
	View(1, 2) = ZAxis.y;
	View(1, 3) = 0;

	View(2, 0) = XAxis.z;
	View(2, 1) = YAxis.z;
	View(2, 2) = ZAxis.z;
	View(2, 3) = 0;

	View(3, 0) = -(D3DXVec3Dot(&XAxis, &Position));
	View(3, 1) = -(D3DXVec3Dot(&YAxis, &Position));
	View(3, 2) = -(D3DXVec3Dot(&ZAxis, &Position));
	View(3, 3) = 1;

	D3DXQuaternionRotationMatrix(&Orientation, &View);

	this->Position = Position;
	this->XAxis = XAxis;
	this->YAxis = YAxis;
	this->ZAxis = ZAxis;
};

void Camera::SetProjection(float FovY, float AspectRatio, float ZNear, float ZFar)
{
	float YScale = 1.0f / tanf(FovY * 0.5f);

	Projection(0, 0) = YScale / AspectRatio; // XScale
	Projection(0, 1) = 0;
	Projection(0, 2) = 0;
	Projection(0, 3) = 0;

	Projection(1, 0) = 0;
	Projection(1, 1) = YScale;
	Projection(1, 2) = 0;
	Projection(1, 3) = 0;

	Projection(2, 0) = 0;
	Projection(2, 1) = 0;
	Projection(2, 2) = ZFar / (ZFar - ZNear);
	Projection(2, 3) = 1;

	Projection(3, 0) = 0;
	Projection(3, 1) = 0;
	Projection(3, 2) = -ZNear * ZFar / (ZFar - ZNear);
	Projection(3, 3) = 0;
};

void Camera::SetPosition(float x, float y, float z)
{
	Position.x = x;
	Position.y = y;
	Position.z = z;

	View(3,0) = -D3DXVec3Dot(&XAxis, &Position);
    View(3,1) = -D3DXVec3Dot(&YAxis, &Position);
    View(3,2) = -D3DXVec3Dot(&ZAxis, &Position);

};

void Camera::Move(float dx, float dy, float dz)
{
	Position += XAxis * dx;
	Position += YAxis * dy;
	Position += ZAxis * dz;

	View(3,0) = -D3DXVec3Dot(&XAxis, &Position);
    View(3,1) = -D3DXVec3Dot(&YAxis, &Position);
    View(3,2) = -D3DXVec3Dot(&ZAxis, &Position);
};

void Camera::SetOrientation(float Yaw, float Pitch, float Roll)
{
	D3DXQuaternionRotationYawPitchRoll(&Orientation, Yaw, Pitch, Roll);
	D3DXQuaternionNormalize(&Orientation, &Orientation);
	D3DXMatrixRotationQuaternion(&View, &Orientation);

	XAxis = D3DXVECTOR3(View(0,0), View(1,0), View(2,0));
    YAxis = D3DXVECTOR3(View(0,1), View(1,1), View(2,1));
    ZAxis = D3DXVECTOR3(View(0,2), View(1,2), View(2,2));

    View(3,0) = -D3DXVec3Dot(&XAxis, &Position);
    View(3,1) = -D3DXVec3Dot(&YAxis, &Position);
    View(3,2) = -D3DXVec3Dot(&ZAxis, &Position);
};

void Camera::SetOrientation(const D3DXQUATERNION& Orientation)
{
    this->Orientation = Orientation;

    D3DXQuaternionNormalize(&this->Orientation, &this->Orientation);
    D3DXMatrixRotationQuaternion(&View, &this->Orientation);

    XAxis = D3DXVECTOR3(View(0,0), View(1,0), View(2,0));
    YAxis = D3DXVECTOR3(View(0,1), View(1,1), View(2,1));
    ZAxis = D3DXVECTOR3(View(0,2), View(1,2), View(2,2));

    View(3,0) = -D3DXVec3Dot(&XAxis, &Position);
    View(3,1) = -D3DXVec3Dot(&YAxis, &Position);
    View(3,2) = -D3DXVec3Dot(&ZAxis, &Position);
};

Some stuff from Game.cpp

D3DXVECTOR3 Position(0.0f, 0.0f, -5.0f);
D3DXVECTOR3 YAxis( 0.0f, 1.0f, 0.0f );
D3DXVECTOR3 XAxis(1.0f, 0.0f, 0.0f);
D3DXVECTOR3 ZAxis(0.0f, 0.0f, 1.0f);
int DeltaMouseX;
int DeltaMouseY;
Camera Cam;
float Yaw;
float Pitch;
...
D3DXMatrixIdentity( &g_World );

Cam.SetView(Position, XAxis, YAxis, ZAxis);

Cam.SetProjection(3.141592f * 0.5f, (float)width / (float)height, 0.1f, 100.0f);
...
Yaw -= (float)DeltaMouseX / 5.0f;
	Pitch -= (float)DeltaMouseY / 5.0f;

	if(Yaw > 360.0f)
		Yaw -= 360.0f;
	if(Yaw < 0.0f)
		Yaw += 360.0f;
	if(Pitch > 360.0f)
		Pitch -= 360.0f;
	if(Pitch < 0.0f)
		Pitch += 360.0f;

	Cam.SetOrientation(D3DXToRadian(Yaw), D3DXToRadian(Pitch), 0.0f);

	DeltaMouseX = 0;
	DeltaMouseY = 0;
	SetCursorPos(0, 0);

	if(Keystate[Key_A] == true)
	{
		Cam.Move(-0.005f, 0.0f, 0.0f);
	}
	if(Keystate[Key_W] == true)
	{	
		Cam.Move(0.0f, 0.0f, 0.005f);
	}
	if(Keystate[Key_D] == true)
	{	
		Cam.Move(0.005f, 0.0f, 0.0f);
	}
	if(Keystate[Key_S] == true)
	{	
		Cam.Move(0.0f, 0.0f, -0.005f);
	}

Someone plz help!!! This is pissing me off!!! [Edited by - xXShadowAsasNXx on September 8, 2009 9:51:21 PM]
Advertisement
Could you edit your post and enclose the code in [source] tags? I'd be happy to look over the code, but it's a bit hard to read at the moment :)

Also, what type of motion are you after here? Are you looking for typical FPS-style camera/object control?
I am trying to make a flight camera.
Not sure if either of these will help, but I have had your problem and this is how I fixed it.

1. Try inverting your viewing matrix. I got this wrong and I had the same problem.

2. If you want more fundamental guides, try drawing a large axis-aligned wire-frame cube around yourself. As you move, it should NOT rotate. Also, perhaps draw a smaller axis-aligned cube centered directly ahead of you. Use absolute coordinates with an identity ((1,0,0),(0,1,0),(0,0,1)) model-view matrix.

I've never used a 3rd party lib for quaternions so I don't know the details of D3DX's version. I also haven't used D3D for 5+ years.

This topic is closed to new replies.

Advertisement