Advertisement

Help with quaternions

Started by April 15, 2003 12:07 PM
2 comments, last by Sonicmage 21 years, 10 months ago
I am having difficulty creating a free-floating camera in Direct3D with quaternions. Here is my Camera class:
  
CCamera::CCamera(){
	pos = new D3DXVECTOR3(0.0f, 0.0f, 0.0f);
	up = new D3DXVECTOR3(0.0f, 1.0f, 0.0f);
	forward = new D3DXVECTOR3(0.0f, 0.0f, 1.0f);
	right = new D3DXVECTOR3(1.0f, 0.0f, 0.0f);
	rotation = new D3DXQUATERNION();
	D3DXQuaternionIdentity(rotation);
	viewFrustum = new CFrustum();
}

CCamera::~CCamera(){
	delete pos;
	delete up;
	delete forward;
	delete right;
	delete rotation;
	delete viewFrustum;
}

void CCamera::SetProjection(LPDIRECT3DDEVICE9 device, bool is3D){
	D3DXMATRIX matProj;
	if(is3D){
		D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 1.0f, 0.1f, 1000.0f );
	}
	else{
		D3DXMatrixOrthoLH( &matProj, 1024.0f, 768.0f, 0.0f, 1.0f);
	}
	device->SetTransform( D3DTS_PROJECTION, &matProj );
}

void CCamera::SetPosition(float x, float y, float z){
	*pos = D3DXVECTOR3(x, y, z);
}

void CCamera::PositionCamera(LPDIRECT3DDEVICE9 device, bool is3D){
	if(is3D){
		D3DXMATRIX out;
		D3DXVECTOR3 fwdVec;
		D3DXVECTOR3 upVec = D3DXVECTOR3(0.0f, 1.0f, 0.0f);
		fwdVec = *pos + *forward;
		D3DXMatrixLookAtLH(&out, pos, &fwdVec, &upVec);
		device->SetTransform( D3DTS_VIEW, &out );
	}
}

//TEMP functions for testing

void CCamera::MoveForward(DWORD dt){
	*pos += 30.0f*((float)dt/1000.0f)*(*forward);
}
void CCamera::MoveBackward(DWORD dt){
	*pos -= 30.0f*((float)dt/1000.0f)*(*forward);
}
void CCamera::MoveLeft(DWORD dt){
	*pos -= 30.0f*((float)dt/1000.0f)*(*right);
}
void CCamera::MoveRight(DWORD dt){
	*pos += 30.0f*((float)dt/1000.0f)*(*right);
}
void CCamera::MoveUp(DWORD dt){
	*pos += 30.0f*((float)dt/1000.0f)*(*up);
}
void CCamera::MoveDown(DWORD dt){
	*pos -= 30.0f*((float)dt/1000.0f)*(*up);
}

void CCamera::RotateCamera(float yaw, float pitch, float roll){
	static float oldPitch = 0.0f;
	if(yaw != 0.0f || pitch != 0.0f || roll != 0.0f){ 
		D3DXMATRIX newRotMatrix;
		D3DXQUATERNION quat;

		oldPitch += pitch;
		if(oldPitch > DegToRad(90.0f)){
			oldPitch = DegToRad(90.0f);
		}
		else if(oldPitch < -DegToRad(90.0f)){
			oldPitch = -DegToRad(90.0f);
		}
		else{
			D3DXQuaternionRotationYawPitchRoll(&quat, yaw, pitch, roll);
			D3DXQuaternionMultiply(rotation, rotation, &quat);
			D3DXMatrixRotationQuaternion(&newRotMatrix, &quat);
			D3DXVec3TransformCoord(forward, forward, &newRotMatrix);
			D3DXVec3Normalize(forward, forward);
			D3DXVec3TransformCoord(up, up, &newRotMatrix);
			D3DXVec3Normalize(up, up);
			D3DXVec3Cross(right, up, forward);
			D3DXVec3Normalize(right, right);
		}
	}
}
  
The program looks as though each Y movement is rotating about the world X-axis instead of the local one. In other words, if I turn 90 degrees about the Y axis (yaw) and then try to change my pitch, it looks like its "roll"ing (but with the up vector always straight up). If I turn a full 180 degrees yaw from the initial orientation, mouse up makes the pitch go down and mouse down makes the pitch go up. I know this must be some simple mistake I''m making, could somebody please provide some help?
Please answer if you can.
Advertisement
why in the world are all those vectors, the quaternion, and the frustrum pointers? use the & if you need to pass its address (to a function that recieves a pointer)
I started out as a Java programmer (cant you tell?) and really, doing it this way has negligible bearing on how much memory I use in my program (an extra 6 pointers, 48 bytes perhaps?) and there''s only going to be one of these cameras in my program.

Please only respond to the problem at hand, not my coding preferences.

This topic is closed to new replies.

Advertisement