Sign in to follow this  
doctorsixstring

Perspective projection problem

Recommended Posts

I have a strange problem. I am currently developing my first DirectGraphics graphics engine. I want to be able to render with an orthogonal projection (for 2D "HUD" graphics) and with a perspective projection (for the 3D objects and game world). I am using index & vertex buffers to render simple objects to the screen. Everything looks good in orthogonal mode, but when I switch the projection transformation, the objects no longer appear on the screen. I [believe] that I have ruled out lighting and geometry issues, due to everything working fine when I am using an orthogonal projection. I am pretty sure that the problem lies with how I am setting up my perspective projection, but there are probably other possibilities. Here is the code I am using to set the current projection to orthogonal or perspective mode:
void RenderTarget::SetOrthoProjection(float width, float height, float min_z, float max_z)
{
	D3DXMATRIX proj, world;
	
	if((int)width==0)
		width = GetSize().x;

	if((int)height==0)
		height = GetSize().y;

	D3DXMatrixOrthoLH(&proj, width, height, min_z, max_z);
	D3DXMatrixIdentity(&world);

	GfxSystem::GetInstance()->GetD3DDevice()->SetTransform(D3DTS_PROJECTION, &proj);
	GfxSystem::GetInstance()->GetD3DDevice()->SetTransform(D3DTS_WORLD, &world);
	BuildViewMatrix();
}

void RenderTarget::SetPerspectiveProjection(float width, float height, float min_z, float max_z)
{
	D3DXMATRIX proj, world;
	
	if((int)width==0)
		width = GetSize().x;

	if((int)height==0)
		height = GetSize().y;

	D3DXMatrixPerspectiveLH(&proj, width, height, min_z, max_z);
	D3DXMatrixIdentity(&world);

	GfxSystem::GetInstance()->GetD3DDevice()->SetTransform(D3DTS_WORLD, &world);
	GfxSystem::GetInstance()->GetD3DDevice()->SetTransform(D3DTS_PROJECTION, &proj);
	BuildViewMatrix();
}

//
//	this is a private function called whenever the view matrix should be updated
//
void RenderTarget::BuildViewMatrix()
{
	D3DXMATRIX trans, rot, final;
	D3DXQUATERNION q;

	D3DXMatrixTranslation(&trans, m_camera_pos.x, m_camera_pos.y, m_camera_pos.z);

	if(m_camera_facing_is_look_at)
	{
		D3DXVECTOR3 eye(m_camera_pos.x, m_camera_pos.y, m_camera_pos.z), 
			lookAt(m_camera_facing.x, m_camera_facing.y, m_camera_facing.z), 
			up(0, 1, 0);
		D3DXMatrixLookAtLH(&rot, &eye, &lookAt, &up);
	}
	else
	{
		D3DXQuaternionRotationYawPitchRoll(&q, m_camera_facing.y, m_camera_facing.x, m_camera_facing.z);
		D3DXMatrixRotationQuaternion(&rot, &q);
	}

	D3DXMatrixMultiply(&final, &trans, &rot);

	GfxSystem::GetInstance()->GetD3DDevice()->SetTransform(D3DTS_VIEW, &final);
}
These three functions are members of my "RenderTarget" class. Objects of this class are used for each window that I am rendering game graphics to. Any thoughts? Need me to clarify anything? Thanks in advance, Mike

Share this post


Link to post
Share on other sites
Kibble    504
What are you passing for the width and height of the perspective matrix? To rule this out as the problem, try using D3DXMatrixPerspectiveFovLH, with PI/2, and an aspect ratio of 4/3. see if the stuff shows up that way.

Share this post


Link to post
Share on other sites
I was using width = 800 and height = 600. I just took your advice and used D3DXMatrixPerspectiveFovLH() instead of D3DXMatrixPerspectiveLH(), and it worked!

Now I can spend the next few hours figuring out why it works now, and how I can work everything together in my engine.

Thanks!

Share this post


Link to post
Share on other sites
Kibble    504
From what I can tell people generally prefer to use FOV as the 'controller' for perspective projection matrices. You may just want to have the function take an FOV and aspect ratio instead. If not, here is what the Direct3D(8) documentation does to calculate both:

// for FOV:
h = cos(fov/2) / sin(fov/2);
w = h / aspect;

2*zn/w 0 0 0
0 2*zn/h 0 0
0 0 zf/(zf-zn) 1
0 0 zn*zf/(zn-zf) 0


// for not-FOV:
2*zn/w 0 0 0
0 2*zn/h 0 0
0 0 zf/(zf-zn) 1
0 0 zn*zf/(zn-zf) 0

so if we use your measurement of 800, the FOV you get is:

800 = cos(fov/2) / sin(fov/2)
1/800 = tan(fov/2)
arctan(1/800) * 2 = .14 degrees

Yes I checked, my calculator was in degree mode. An FOV of .14 is like looking through a pinhole 1 foot from your face.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this