Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I am facing a problem in mapping 3d co-ordinate to screen co-ord . I require it because i want to draw text on the model . model is drawn at the 3d-cordinate, so if i know the position of that co-ord on the screen i can draw text at that position.

my view is on z axis test position is on x axis

In the follwing code I did what i said above but the transformation is not happening the way it should i.e, text should appear on the model

float aspectRatio = graphics.GraphicsDevice.Viewport.AspectRatio;
Vector2 screenOrigin = new Vector2(GraphicsDevice.Viewport.Width / 2, GraphicsDevice.Viewport.Height / 2);
Vector3 testPosition = new Vector(10,0,0);
Vector3 cameraPosition = new vector(0,0,50),

Matrix world = Matrix.Identity;
Matrix view = Matrix.CreateLookAt(cameraPosition,Vector3.Zero, Vector3.Up);
Matrix projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45.0f), aspectRatio, 1.0f, 10000.0f);

Matrix totalEffect = world * view * projection;

Vector2 spritePos = getXYPosition(vecAndMatMultiplication(testPosition, totalEffect))+screenOrigin;

Where vecAndMatMultiplication() multiplies vector with the matrix and getXYpostion() should be fairly obvious.

share|improve this question
    
You could set your target render to a texture, render the text on it, then apply the texture just once on the sphere. Seems easier and less calculations. –  Gustavo Maciel May 3 '12 at 7:52
    
Wait, how exactly are you rendering the text? Do you want it to look like it's part of the model and wrap around the sphere's curvature? Or you just want to add a text label to the model at the correct position? Because from the content of your question and the example you wrote, it seemed like the second option, hence my answer. The first scenario would naturally require rendering to a texture and using it to render the sphere. –  David Gouveia May 3 '12 at 7:58
    
I think the title of the question does not reflect what you seem to be asking, which is how to convert coordinates from 3D world space to 2D screen space. –  David Gouveia May 3 '12 at 8:32
add comment

1 Answer 1

up vote 0 down vote accepted

Short Answer

Use the Viewport.Project method that already does the work for you (link to documentation):

Viewport viewport = GraphicsDevice.Viewport;
Vector3 screenPosition = viewport.Project(worldPosition, projection, view, world);
Vector2 spritePosition = new Vector2(screenPosition.X, screenPosition.Y);

So, just call it with the correct matrices, and ignore the Z value of the result.

Long Answer

If you want to understand what you are doing wrong in your example, it's basically because the correct procedure is not just to multiply the position by the WorldViewProjection matrix and add the screen origin. There's a little bit more to it than that.

The actual procedure is to:

  • Expand position into a Vector4 such as (x,y,z,1)
  • Multiply that Vector4 by the WorldViewProjection matrix.
  • Homogenize the result back into a Vector3 by doing (x/w, y/w, z/w)
  • Apply the viewport transformation to map from (-1,-1,1,1) range to the the viewport and flip the Y axis so that it runs top-bottom instead of bottom-up:

    screenX = viewportX + viewportW * (x + 1.0) * 0.5
    screenY = viewportY + viewportH * (1.0 - y) * 0.5
    

I have not tested the following bit of code, but I think the implementation should be something like this:

public static Vector2 ConvertWorldToScreen(Vector3 source, Matrix world, Matrix view, Matrix projection, Viewport viewport)
{
    Vector4 result = Vector4.Transform(new Vector4(source, 1), world * view * projection);
    result /= result.W;
    float screenX = (float)viewport.X + (float)viewport.Width * (result.X + 1.0f) * 0.5f;
    float screenY = (float)viewport.Y + (float)viewport.Height * (1.0f - result.Y) * 0.5f;
    return new Vector2(screenX, screenY);
}
share|improve this answer
    
But don't use my implementation, that was merely illustrative. Use Viewport.Project instead which is slightly optimized. –  David Gouveia May 3 '12 at 8:42
    
Short answer works fine , but i want to know more about how to implement text wrapping on a model. Can you point me to some text/video resource –  gamechanger May 3 '12 at 9:55
    
@gamechanger Take a look at the "Render to Texture" section of this answer. You would need to create a RenderTarget2D and render the model's texture and the text to it. Then use that RenderTarget2D as the texture for rendering the model. The difficult part is calculating the right place in the texture to render the text. Don't have any link for a direction solution to that problem. –  David Gouveia May 3 '12 at 10:04
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.