Jump to content
  • Advertisement
Sign in to follow this  
the-beast

3D to 2D coords

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

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, a few months back I created a C++/DirectX8 based solar system model. I have now come back to this project and have decided to add some lens flare code to the program. The problem I have is converting the 3D coordinates of my Sun into 2D screen coordinates. Standard Info: The sun is always at position (0, 0, 0) on the 3D side of things, but the camera is movable and so the 2D screen coords are constantly changing. 1. I need some code to calculate where the sun is on the screen at any given time. 2. I also need to know the intensity of the light, when the sun is in the middle of the screen the light should be the brightest. At the moment the sun is a constant and only light source in the solar system. Should I add a second light source for the intensity of the lens flare or should I alter the value of the suns light source? Any help would be very much appreciated. Thanks. Edit - Almost forgot I'm using VS 6 and DirectX 9.0b SDK.

Share this post


Link to post
Share on other sites
Advertisement
Normally, I use D3DXProject() or D3DXUnproject() (although there are other ways to do it).

Unproject() is the way you would go from world to screen.

Basically, put your object's screen position into a vector and unproject it to get it into your screen space, passing the current matrices and viewport along as well.

Share this post


Link to post
Share on other sites
Thanks for the response. Unfortionatly the C++ compiler complains that D3DXUnproject() is an undeclared identifier and a search of the DX help files does not even list this as a valid function (at least on my comp).

Don't suppose that you could give me a quick example of this function in use and of the headers/libraries that I need to get the function to be recognised?



If this helps I am including the code that I use to get the Sun to be rendered.


D3DXMATRIX matSun, matScaleSun, matRotateSun, matSunRoll, matSunMove;

//For the sun
D3DXMatrixRotationY(&matRotateSun, D3DXToRadian(m_rAngle));
D3DXMatrixScaling(&matScaleSun, m_rScale, m_rScale, m_rScale);
D3DXMatrixRotationYawPitchRoll(&matSunRoll, 0.0f, 0.0f, D3DXToRadian(0.00f));

D3DXMatrixTranslation(&matSunMove, 0, 0, 0.0f); //Do not move the Sun

D3DXMatrixMultiply(&matSun, &matScaleSun, &matRotateSun);
D3DXMatrixMultiply(&matSun, &matSun, &matSunRoll);
D3DXMatrixMultiply(&matSun, &matSun, &matSunMove);

m_pD3DDevice->SetTransform(D3DTS_WORLD, &matSun);
m_dwTotalPolygons += m_pMesh0->Render();



The render function in the line above consists of

DWORD CMesh::Render()
{
if(m_pMesh != NULL)
{
for(DWORD i = 0; i < m_dwNumMaterials; i++)
{
m_pD3DDevice->SetMaterial(&m_pMeshMaterials);
m_pD3DDevice->SetTexture(0, m_pMeshTextures);

m_pMesh->DrawSubset(i);
}

return m_pMesh->GetNumFaces();
}
else
{
return 0;
}
}



[Edited by - Coder on September 29, 2004 2:46:08 PM]

Share this post


Link to post
Share on other sites
I also have this for the viewport/view matrix (is this the same thing)

D3DXMATRIX mView;

//Initialise the view matrix to an identity
D3DXMatrixIdentity( &mView );

//Fill in the view matrix
mView(0,0) = m_Right.x;
mView(0,1) = m_Up.x;
mView(0,2) = m_LookAt.x;

mView(1,0) = m_Right.y;
mView(1,1) = m_Up.y;
mView(1,2) = m_LookAt.y;

mView(2,0) = m_Right.z;
mView(2,1) = m_Up.z;
mView(2,2) = m_LookAt.z;

mView(3,0) = - D3DXVec3Dot( &m_Position, &m_Right );
mView(3,1) = - D3DXVec3Dot( &m_Position, &m_Up );
mView(3,2) = - D3DXVec3Dot( &m_Position, &m_LookAt );

//Set the view matrix
m_pD3DDevice->SetTransform( D3DTS_VIEW, &mView );

//Set the perspective
SetPerspective(m_pD3DDevice);

//Make sure that the z-buffer and lighting are enabled
m_pD3DDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
m_pD3DDevice->SetRenderState(D3DRS_LIGHTING, TRUE);
}

//*************************************************************************************************************

//This is not in the book, but the camera in my program does not work without it
void CCamera::SetPerspective(LPDIRECT3DDEVICE8 m_pD3DDevice)
{
//Here we specify the field of view, aspect ration and near and far clipping planes.
D3DXMATRIX ProjectionMatrix;
ZeroMemory( &ProjectionMatrix, sizeof( D3DXMATRIX ) );

float ScreenAspect = (float)m_nScreenWidth / (float)m_nScreenHeight;
float FOV = D3DX_PI / 4;

//Last value represents view distance
//D3DXMatrixPerspectiveFovLH( &ProjectionMatrix, FOV, ScreenAspect, 1.0f, 4000.0f );
D3DXMatrixPerspectiveFovLH( &ProjectionMatrix, FOV, ScreenAspect, 1.0f, 65000.0f );
//Above: View now reaches Pluto (How will this affect performance??????)

m_pD3DDevice->SetTransform( D3DTS_PROJECTION, &ProjectionMatrix );
}



[Edited by - Coder on September 29, 2004 2:50:00 PM]

Share this post


Link to post
Share on other sites
Sorry, bub. You're right. The exact function is D3DXVec3Project() or D3DXVec3Unproject(). I was going from memory. And, I think I was backwards with the functions. I think you need Project().

But, it is definitely documented under the D3DX extensions.

-- The first paramemeter is your target vector.
-- The next parameter is your source vector.
-- The next four are your current viewport, projection, view, and world matrices respectiviely.

..

Unfortuantely, all my work is being done in Managed DX these days (day job and side projects), so I don't have a regular DX example I can quickly whip up. But, it's pretty straightforward. Just make sure your current matrices and viewport are stored somewhere. With that knowledge, Project should be able to put your world coordinates into screen space.

In C#.Net, all I do is this:


internal static Vector3 WorldPositionFromScreen(Vector3 screenVector)
{
get
{
return screenVector.Unproject(_engine.Device.Viewport,
_engine.Camera.ProjectionMatrix,
_engine.Camera.ViewMatrix,
Matrix.Identity);
}
}

internal static Vector3 ScreenPositionFromWorld(Vector3 worldVector)
{
get
{
return worldVector.Project(_engine.Device.Viewport,
_engine.Camera.ProjectionMatrix,
_engine.Camera.ViewMatrix,
Matrix.Identity);
}
}




In this above example, my engine exposes the current viewport, projection matrix, and view matrix. I use the Identity matrix because I just want things put into regular screen space...
.

Share this post


Link to post
Share on other sites
Thanks The Frugal Gourmet, will try out later and post back on my success.

Coder - Sorry about that I was looking for source/code tags before, didn't realise they were in the FAQ!!!

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
OK, finally had time to try out that DirectX function and it work. Thanks for the advice The Frugal Gourmet.

If anyone else is interested the code that I finally used was:


D3DXVECTOR3 m_SunDirection;
m_SunDirection = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
D3DXVECTOR3 result;
D3DXVec3Project(&result, &m_SunDirection, &vp, &m_pCamera->GetProjectionMatrix(), &m_pCamera->GetCameraMatrix(), &GetWorldMatrix());

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!