• 11
• 14
• 12
• 10
• 11

Crazy Camera Happenings When Pointing Straight Down

This topic is 4710 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

First to qualify I am using C++ and Direct3D 9c. Ok, so If I have a grid of tiles at height zero stretching from 0,0 to 64,64 and then have my camera looking directly down (target{32,0,32}, source{32,128,32}), for some reason it renders nothing. If I shift the camera source slightly (ie target{32,0,32}, source{32,128,31}) it renders. Why does it not render when pointing directly down? I am using the source and target to setup the view matrix using... // set view transform D3DXVECTOR3 vUp(0.0f, 1.0f, 0.0f); D3DXMatrixLookAtLH(&matView, &vSource, &vTarget, &vUp); if (FAILED(InDevice.SetTransform(D3DTS_VIEW, &matView))) return FALSE; Thanks PS, also how do I mark code to show in the window properly?

Share on other sites
You're forward vector is parallel to your world up vector, which is a problem. The purpose of the world up vector is to select a camera up vector of the correct orientation. Basically, the camera forward vector, up vector, and the world up vector all need to be coplanar. Once you make the forward vector essentially the same as the world up vector, you only really have 2 lines and coplanar becomes no restriction at all; ie. any 2 lines are coplanar if you only have 2 lines (just like there's a straight line between any two points).

Hope I was clear :S.

Share on other sites
Quote:
 Original post by devin_papineauYou're forward vector is parallel to your world up vector, which is a problem. The purpose of the world up vector is to select a camera up vector of the correct orientation. Basically, the camera forward vector, up vector, and the world up vector all need to be coplanar. Once you make the forward vector essentially the same as the world up vector, you only really have 2 lines and coplanar becomes no restriction at all; ie. any 2 lines are coplanar if you only have 2 lines (just like there's a straight line between any two points).Hope I was clear :S.

Ok, first of all, I am NOT a forward vector. Second of all... huh!?

Only joking! So you're saying that the vector between the camera source and position cannot be the same as my world up vector? You talk about a camera up vector and a world up vector... are these two seperate things?

Share on other sites
"Up" is not a reference to a direction (0,1,0). It's where the top of your head points to.
So when you're looking down, it points to the front (0,0,1) (actually, it could point at any direction: (sin(x),0,cos(x)) for any x).

For normal world rendering, it has to be orthogonal to your camera direction.

Clearer?

Share on other sites
Sorry about that. I guess when I type I think mostly in terms of speaking than writing. Anywho:

A rotation matrix on some level corresponds to some vectors in relation to the camera (well for the camera anyway). There's the forward vector, the up vector, and the right vector (pretty much the new z, y, and x directions). Given the camera's position and the point it's looking at, you can determine forward. Up could be any line perpendicular to forward, so we use a world up vector (that's your &vUp) to determine it. We choose the up vector that is coplanar with forward and world up. Then right is basically a cross product. Now with only two lines (which is essentially what happens if your forward and world up vectors are parallel), coplanar becomes meaningless. It could once again be any old line. That's why it's funky, if I understand correctly. If I remembered where I read all this, I'd linkify it. That would probably be more clear than my ramblings.

Share on other sites
Quote:
 Original post by devin_papineauSorry about that. I guess when I type I think mostly in terms of speaking than writing. Anywho:A rotation matrix on some level corresponds to some vectors in relation to the camera (well for the camera anyway). There's the forward vector, the up vector, and the right vector (pretty much the new z, y, and x directions). Given the camera's position and the point it's looking at, you can determine forward. Up could be any line perpendicular to forward, so we use a world up vector (that's your &vUp) to determine it. We choose the up vector that is coplanar with forward and world up. Then right is basically a cross product. Now with only two lines (which is essentially what happens if your forward and world up vectors are parallel), coplanar becomes meaningless. It could once again be any old line. That's why it's funky, if I understand correctly. If I remembered where I read all this, I'd linkify it. That would probably be more clear than my ramblings.

So, you are saying that my camera direction, and my world up are used to calculate some kind of plane that is used for rendering. Because they are both parallel to each other this plane cannot be calculated? Kind of makes sense.

Share on other sites
Here I think I found it: clicky.

Share on other sites
Quote:
 Original post by devin_papineauHere I think I found it: clicky.

Ok, gonna take me a while to read through, thanks for the link. I amended my code to make the vUp orthogonal (I am sure there is a much quicker way of doing it, but it seems to work)...

// calculate orthogonal vector for world up (top of head)

// set view transform
D3DXMatrixLookAtLH(&matView, &vSource, &vTarget, &vUp);
if (FAILED(InDevice.SetTransform(D3DTS_VIEW, &matView)))
return FALSE;

Share on other sites
just cap your rotation so your forward vector is never equal to the positive or negative world up vector (0,1,0) or (0,-1,0) because the cross product of two vectors that are the same is an undefined behavior

	void CCamera::Pitch(float fAngle)	{		D3DXMATRIX mat;		//	this is going to be our epsilon to determine 		//	if the dotproduct is too close to one - this is for our capping value		const float fEpsilon = 0.1f;		D3DXMatrixRotationAxis(&mat, &mRight, fAngle);		D3DXVec3TransformCoord(&mUp, &mUp, &mat);		D3DXVec3TransformCoord(&mAt, &mAt, &mat);		float dotVal = abs(D3DXVec3Dot(&mAt, &vGlobalUp));		float minVal = min(dotVal, 1.0f);		float maxVal = max(dotVal, 1.0f);		//	this should cap the rotation if our forward vector gets too close		//	to the global up vector (if we look straight up) 		//	If the dot product of the At-Vector and Global Up is too close to 1 		//	that means we are close to having the same vector.		if( maxVal - minVal < fEpsilon )		{			//	rotate back to where we were before			D3DXMatrixRotationAxis(&mat, &mRight, -fAngle);			D3DXVec3TransformCoord(&mUp, &mUp, &mat);			D3DXVec3TransformCoord(&mAt, &mAt, &mat);		}			}

This is assuming that you are calculating your matrix similar to the following...
	void CCamera::GetViewMatrix(D3DXMATRIX *pOut)	{            if( !pOut )return;	      D3DXMATRIX &out = *pOut;				D3DXVec3Normalize(&mAt, &mAt);		const D3DXVECTOR3 yaxis(0.0f, 1.0f, 0.0f);				//	using the global up (y-axis) keeps our head feeling like it should while doing the		//	mouse look...		D3DXVec3Cross(&mRight, &yaxis, &mAt);		D3DXVec3Normalize(&mRight, &mRight);				D3DXVec3Cross(&mUp, &mAt, &mRight);		D3DXVec3Normalize(&mUp, &mUp);		out(0,0) = mRight.x;		out(0,1) = mUp.x;		out(0,2) = mAt.x;		out(0,3) = 0.0f;		out(1,0) = mRight.y;		out(1,1) = mUp.y;		out(1,2) = mAt.y;		out(1,3) = 0.0f;		out(2,0) = mRight.z;		out(2,1) = mUp.z;		out(2,2) = mAt.z;		out(2,3) = 0.0f;		out(3,0) = -D3DXVec3Dot(&mRight, &mPos);		out(3,1) = -D3DXVec3Dot(&mUp, &mPos);		out(3,2) = -D3DXVec3Dot(&mAt, &mPos);		out(3,3) = 1.0f;	}

This is from an old camera class of mine that I don't really use any more, so I'm sure there are plenty of optimizations that can be made.

hth
moe.ron