3D to 2D 1:1 Mapping?

Started by
6 comments, last by ChrisLamothe1970 16 years, 12 months ago
Hello, I've created and rendered a textured quad (my game board). My vertex buffer uses the D3DFVF_XYZRHW flag (effectively giving me screen coordinates for displaying my textured quad). I want to translate this texture. Obviously, I can do this by directly manipulating my vertex buffer values and then reloading them in my Render method. However, I'd prefer to use a combination of the D3DFVF_XYZ flag and an Orthogonal projection and a Matrix Translation. My screen size (back buffer) is 640x480. Am I right by thinking that the coordinate system I am converting from (World) has limits from L-R of: -1 to +1 and the same for Top-Bottom? So, do I just need to do a 2/screen_width and 2/screen_height to get the Translation value (between World and Screen) that will move the quad one screen pixel in either direction? If so, is this guaranteed to be a 1:1 mapping? Thanks for any help. Chris
Advertisement
Quote:Original post by ChrisLamothe1970
My screen size (back buffer) is 640x480. Am I right by thinking that the coordinate system I am converting from (World) has limits from L-R of: -1 to +1 and the same for Top-Bottom?

Yes. You can convert from these coordinates to screen pixels like: PixelCoord = (VertexCoord + 1) * 0.5 * ScreenSize

Quote:Original post by ChrisLamothe1970
So, do I just need to do a 2/screen_width and 2/screen_height to get
the Translation value (between World and Screen) that will move the
quad one screen pixel in either direction?

Yes, that's right.

Quote:Original post by ChrisLamothe1970
If so, is this guaranteed to be a 1:1 mapping?

Yes, although you may not get exact mapping of textels to pixels. With D3DFVF_XYZRHW you would use -0.5 displacement to correctly map textels to pixels, but in the case of XYZ this won't be that easy. You can try applying the displacement in the vertex shader though.
Getting a 1:1 mapping should be possible if you're careful, but have you considered going for a proportional system instead? E.g. Defining your tiles in percentage of screen width/height rather than pixels?

One advantage of this is that you can become resolution independent - if I were to play your 640x480 game on my 20." 1600x1200 flat panel it would look pretty horrific to be honest. Flat Panel's rarely scale well and are best left in their native resolution...

hth
Jack

<hr align="left" width="25%" />
Jack Hoxley <small>[</small><small> Forum FAQ | Revised FAQ | MVP Profile | Developer Journal ]</small>

Guys,

Thanks very much for your responses.

I have tried experimenting with the following but I cannot see my
texture ...


-------------------

** Vertex buffer with quad texture coordinates that the four corners
of the screen ().

#define D3DFVF_CUSTOMVERTEX ( D3DFVF_XYZ | D3DFVF_TEX1 )

Vertex g_quadVertices[] =
{
{0.0f, 0.0f, 1.0f, 0.0f,0.0f }, // screen limits - 2/640f, 2/480f
{0.003125f, 0.0f, 1.0f, 1.0f,0.0f },
{0.0f, 0.004166f, 1.0f, 0.0f,1.0f },
{0.003125f, 0.004166f, 1.0f, 1.0f,1.0f }
};


-------------------

** Plain vanilla Orthographic camera / view volume:


D3DXMatrixOrthoLH(&matOrtho, 640.0f, 480.0f, 0.1f, 10.0f); // View
volume of 2/640f, 2/480f
D3DXMatrixIdentity (&matIdentity);
g_pd3dDevice->SetTransform (D3DTS_PROJECTION, &matOrtho);
g_pd3dDevice->SetTransform (D3DTS_WORLD, &matIdentity);
g_pd3dDevice->SetTransform (D3DTS_VIEW, &matIdentity);


-------------------


** Render() method to draw:

D3DXMATRIX matWorld;
D3DXMatrixTranslation( &matWorld, 0.00625f, 0.00833f, 2.0f ); //
move the texture to the middle of the screen - 2/320f, 2/240f
g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );

g_pd3dDevice->BeginScene();

g_pd3dDevice->SetTexture( 0, g_pTexture );
g_pd3dDevice->SetStreamSource( 0, g_pVertexBuffer, 0, sizeof(Vertex) );
g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );

g_pd3dDevice->EndScene();
g_pd3dDevice->Present( NULL, NULL, NULL, NULL );


-------------------


Any ideas what [stupid] mistake I've made?!!

Cheers,
Chris
I'm not sure what can be the cause of the problem, but notice that not all your vertex coordinates have "w" part set to 1.0f. If I would you, I'd first try to render the quad without any transformations whatsoever with positions (-1, 1), (1, 1), (1, -1), (-1, -1) [note that Y coordinate of 1 corresponds to top of the screen] to fill the entire screen first.

Also, make sure to disable any lighting and culling states.
LifePower,

Yes, I have had the texture displayed using texture coordinates, that's no problem.

** QUESTION: Am I right in thinking that you *cannot* give screen coordinates to a texture-based vertex buffer (these *must* be the conventional -1 to +1 etc)?


I can move my texture "1 pixel" in any direction but this obviously depends on the screen metrics (640x480)....

This is what Jack was hinting at I think.

So if someone changes the size of my DX window then my 2.0f/640.0f value won't be valid for a 1:1 world-to-screen (i.e., single pixel) x-coordinate translation.


I really appreciate all of your responses.
Let me know if you've anything further to add.

Cheers,
C
Quote:Original post by ChrisLamothe1970
** QUESTION: Am I right in thinking that you *cannot* give screen coordinates to a texture-based vertex buffer (these *must* be the conventional -1 to +1 etc)?
Not 100% sure what you mean here, but texture coordinates (used to lookup the pixels from a texture being mapped to a triangle) are typically in 0.0 to 1.0 (although repeating allows more)....

Quote:Original post by ChrisLamothe1970
This is what Jack was hinting at I think.

So if someone changes the size of my DX window then my 2.0f/640.0f value won't be valid for a 1:1 world-to-screen (i.e., single pixel) x-coordinate translation.
Yes, but as is true with software development in general - hard coding constants like you have is a recipe for disaster [smile]

Not only is it hard to change if YOU know about a change of environment, but its pretty much impossible for the application to adapt on its own once you've distributed it and can no longer change the source code...

IDirect3DDevice9::GetDisplayMode() might be useful, but I'm not sure how well that works outside of fullscreen modes...

hth
Jack

<hr align="left" width="25%" />
Jack Hoxley <small>[</small><small> Forum FAQ | Revised FAQ | MVP Profile | Developer Journal ]</small>

Jack,

Thanks again for your speedy response.

The idea is that I'm trying to write a simple Google-style map sheet (terrain). Essentially this will shrink and grow etc...

I was using the screen coordinates FVF approach but found that I could not then use the D3DX scaling/tranlation matrices etc...

I decided to use the conventional FVF_XYZ approach and use texture coordinates in my vertex buffer. The question I was asking is, can you use absolute screen coordinates in a texture-based vertex buffer. (as in the FVF_XYZRHW approach)?

Or, as I suspect, do I have to convert my absolute screen coordinates (that come back as a result of moving the mouse) back into the -1 to +1 range (and manually adjust the Vertex buffer) before sending the vertices into the usual:

g_pd3dDevice->SetTexture( 0, myTexture );
g_pd3dDevice->SetStreamSource( 0, g_pVertexBuffer, 0, sizeof(Vertex) );
g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );


** Jack as you're bring so kind as to answer my questions I wonder if you know of anyone that has done what I'm trying to achieve using DX9 (i.e., a 2D game board)?

Thanks very much for your time,
C

This topic is closed to new replies.

Advertisement