• Create Account

## Screen to world coordinates

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

3 replies to this topic

### #1MatsK  Members

361
Like
0Likes
Like

Posted 05 August 2012 - 11:22 AM

Hi!
I'm rendering 3D on top of 2D, and it seems to be working, but I need to be able to render a specific mesh at, say - 10, 10 in screen coordinates.
How?

My current approach involves using Viewport.Unproject(), but it doesn't seem to be working;

[source lang="csharp"] Vector3 NearScreenPoint = new Vector3(0, 0, 0); Vector3 FarScreenPoint = new Vector3(0, 0, 1); Vector3 NearWorldPoint = m_Scene.SceneMgr.Device.Viewport.Unproject(NearScreenPoint, m_Scene.SceneMgr.ProjectionMatrix, m_Scene.SceneMgr.ViewMatrix, m_Scene.SceneMgr.WorldMatrix); Vector3 FarWorldPoint = m_Scene.SceneMgr.Device.Viewport.Unproject(FarScreenPoint, m_Scene.SceneMgr.ProjectionMatrix, m_Scene.SceneMgr.ViewMatrix, m_Scene.SceneMgr.WorldMatrix); Vector3 Direction = FarWorldPoint - NearWorldPoint; Direction.Normalize(); if (m_CurrentHeadMeshes.Count > 0) { for (int i = 0; i < m_CurrentHeadMeshes[0].VertexTexNormalPositions.Length; i++) { /*Vector4 Position = new Vector4(m_CurrentHeadMeshes[0].VertexTexNormalPositions[i].Position, 1); Matrix WorldMat = Matrix.CreateWorld(new Vector3(0, 0, 0), Vector3.Forward, new Vector3(0, 1, 0)); Vector4.Transform(ref Position, ref WorldMat, out Position); Position /= Position.W; m_CurrentHeadMeshes[0].VertexTexNormalPositions[i].Position.X = Position.X; m_CurrentHeadMeshes[0].VertexTexNormalPositions[i].Position.Y = Position.Y; m_CurrentHeadMeshes[0].VertexTexNormalPositions[i].Position.Z = Position.Z;*/ m_CurrentHeadMeshes[0].VertexTexNormalPositions[i].Position *= Direction; } }[/source]

I also want to rotate the mesh around it's X-axis, but I commented out the code for doing that since it complicated things. Anyway, here is my entire code:

Also, here's my View, World and Projection:

[source lang="csharp"] m_WorldMatrix = Matrix.Identity; m_ViewMatrix = Matrix.CreateLookAt(Vector3.Backward * 5, Vector3.Zero, Vector3.Right); m_ProjectionMatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.Pi / 4.0f, (float)Device.PresentationParameters.BackBufferWidth / (float)Device.PresentationParameters.BackBufferHeight, 1.0f, 100.0f);[/source]

I've been Googling around for answers to this issue for some time now, but everything seems to revolve around picking, which isn't helping me.

### #2Koder4Fun  Members

146
Like
0Likes
Like

Posted 06 August 2012 - 04:24 AM

If I understood correctly you want to draw 3d elements on the graphics user interface of your game.
You are right, you can use Unproject() but the parameters you feed are incorrect.

Near and far points must contain:
Vector3 NearScreenPoint = new Vector3(cx, cy, 0);
Vector3 FarScreenPoint = new Vector3(cx, cy, 1);

where cx and cy are the position in pixels referred to the current viewport (so take care of what is the current active viewport).

Now you can calculate Direction using:
Direction = Vector3.Lerp(NearScreenPoint, FarScreenPoint, dist);

where dist is a number in range [0..1] to choice the distance of your 3D object from the camera. If you use 0 or 1 you can't see the object, it's clipped away.

Now, to render the object I think is better to use a translation matrix or, more simpler, to send the Direction vector to a shader that do the per-vertex transform on the GPU adding Direction to the mesh vertex position. If you do this on CPU you waste time.

If i'm not clear please post.

Edited by Koder4Fun, 06 August 2012 - 04:26 AM.

Marco Sacchi
Coding is a challenge ... but solving problems is the fun part
My Blog - XNA Italian portal

### #3MatsK  Members

361
Like
0Likes
Like

Posted 06 August 2012 - 02:08 PM

Yes, I found out it was easier to just apply a translation matrix to the world matrix, as such:

As is evident from that snippet, I changed the class to function more as a renderingcontext, which was more in line with what I had originally intended. I also realized pretty quickly that I needed to scale, and I had to do that using the viewmatrix. Somehow, that affected the coordinatesystem, so I had to update my coordinates for where I wanted to render the mesh as I moved the viewmatrix further away. I'm still not 100% sure how to handle scaling because of this very issue. For now, I've just hardcoded it:
[source lang="csharp"]m_Effects[i].View = Matrix.CreateLookAt(Vector3.Backward * 17, Vector3.Zero, Vector3.Right);[/source]

### #4Koder4Fun  Members

146
Like
0Likes
Like

Posted 11 August 2012 - 04:33 AM

You can chain all needed matrix transforms, you only need to be care with the order of multiplication:

ComboMatrix = TranslationMatrix * ScaleMatrix * RotationMatrix;


To keep in mind the correct order read the transformations in a right to left direction, and you can see how the vertices of a mesh are transformed from the stored local-space coordinates to world-space coordinates.

This way you can calculate the matrix one time and apply it to all objects you want.