Sign in to follow this  

"Relative" vertex positions...?

This topic is 4554 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

Yeah, so I'm new to all this Direct3D malarky. Essentially I'm trying to get the very basics down, and get a square rendered. I've got it all sorted, so the VertexBuffer carries a four sided shape, with each side having equal length, but when it comes to render it's longer than it is tall. I found out this is because of the dimensions of the window; when I set it to a square window, the shape is displayed square. I'm just trying to get some simple 2D stuff under my belt so I can make a simple Tetris/whatever clone. I've been reading various tutorials, such as Drunken Hyena's page, but I couldn't find specific information on how to get a square to display square. If anyone can forward me to details behind the theory, and/or code that'd be much appreciated. Thanks a lot.

Share this post


Link to post
Share on other sites
You have to make the aspect ratio of your projection (viewing frustrum) correspond to the aspect ratio of the window. You want to do 2D, so I suppose you use this projection matrix:

link to msdn

If your window has dimensions window_width and window_height, you have to make sure that the w and h parameters of the D3DXMatrixOrthoLH function are created using the following formula:

w/h = window_width / window_height

Obviously, you still have to choose either w or h yourself. The other one can then be computed.

edit:
window_width and window_height, should actually be the dimensions of the client area (the part of the window without borders and title bar). Look at the AdjustWindowRectEx function to create a window with the correct client area size.

Share this post


Link to post
Share on other sites
Yeah, the msdn link didn't work, I'm assuming cos of their silly frames thing.

But anyway, I tried this:

Quote:

D3DXMATRIX ortho2D;
D3DXMATRIX identity;

D3DXMatrixOrthoLH(&ortho2D, width, height, 0.0f, 1.0f);
g_D3DDevice->SetTransform(D3DTS_PROJECTION, &ortho2D);
g_D3DDevice->SetTransform(D3DTS_WORLD, &identity);
g_D3DDevice->SetTransform(D3DTS_VIEW, &identity);


...where width and height are the adjusted dimensions of the window, and yeah, basically nothing got drawn :

Share this post


Link to post
Share on other sites
Quote:
Original post by BigFreak
Yeah, the msdn link didn't work, I'm assuming cos of their silly frames thing.

But anyway, I tried this:

Quote:

D3DXMATRIX ortho2D;
D3DXMATRIX identity;

D3DXMatrixOrthoLH(&ortho2D, width, height, 0.0f, 1.0f);
g_D3DDevice->SetTransform(D3DTS_PROJECTION, &ortho2D);
g_D3DDevice->SetTransform(D3DTS_WORLD, &identity);
g_D3DDevice->SetTransform(D3DTS_VIEW, &identity);


...where width and height are the adjusted dimensions of the window, and yeah, basically nothing got drawn :


You need to initialize the identity matrices also, with D3DXMatrixIdentity - an identity matrix does not equal an empty matrix (array of 0:s).

Share this post


Link to post
Share on other sites
Quote:
Original post by BigFreak
Yeah, the msdn link didn't work, I'm assuming cos of their silly frames thing.

My bad:
Quote:

Syntax

D3DXMATRIX *WINAPI D3DXMatrixOrthoLH( D3DXMATRIX *pOut,
FLOAT w,
FLOAT h,
FLOAT zn,
FLOAT zf
);
Parameters

pOut
[in, out] Pointer to the D3DXMATRIX structure that contains the resulting matrix.
w
[in] Width of the view volume.
h
[in] Height of the view volume.
zn
[in] Minimum z-value of the view volume which is referred to as z-near.
zf
[in] Maximum z-value of the view volume which is referred to as z-far.

Return Value
Pointer to a D3DXMATRIX structure that is a left-handed orthogonal projection matrix.


Quote:

...where width and height are the adjusted dimensions of the window, and yeah, basically nothing got drawn :

Do you do everything exactly as before, except for computing the h-parameter from your window size and the w-parameter?

Share this post


Link to post
Share on other sites
Yeah, I did everything else the same, but I don't really understand what you meant by this:
Quote:

If your window has dimensions window_width and window_height, you have to make sure that the w and h parameters of the D3DXMatrixOrthoLH function are created using the following formula:

w/h = window_width / window_height

Obviously, you still have to choose either w or h yourself. The other one can then be computed.

edit:
window_width and window_height, should actually be the dimensions of the client area (the part of the window without borders and title bar). Look at the AdjustWindowRectEx function to create a window with the correct client area size.


Surely if:

w/h = window_width / window_height

it's implied that w can be equal to window_width, and h can be equal to window_height? This is currently how I have then, equal to the dimensions of the window.

Share this post


Link to post
Share on other sites
Quote:
Original post by BigFreakSurely if:

w/h = window_width / window_height

it's implied that w can be equal to window_width, and h can be equal to window_height? This is currently how I have then, equal to the dimensions of the window.

True. You can make them equal. But you shouldn't :) Think about it. w and h are the size of "the screen" expressed in the same units as the world coordinates (more or less). If you make this really, really big (eg. 640 x 480, compared to the 1 or 10 of z_near, and the dimensions of the quad you try to draw) the object you try to draw wil appear smaller. Maybe it gets so small, that you can't see it anymore. I don't know if this is actually the case, but try using something in the range of z_near, or simply use the value for w you used before, and only compute the value of h from there.
If you insist on making w and h equal to the window size, you should also adjust your other dimensions accordingly.
I hope this solves your problem...

Share this post


Link to post
Share on other sites
OK, so I have this:
Quote:

D3DXMATRIX ortho2D;
D3DXMATRIX identity;

D3DXMatrixOrthoLH(&ortho2D, (float)1, (float)0.75, 0.0f, 1.0f);
D3DXMatrixIdentity(&identity);
g_D3DDevice->SetTransform(D3DTS_PROJECTION, &ortho2D);
g_D3DDevice->SetTransform(D3DTS_WORLD, &identity);
g_D3DDevice->SetTransform(D3DTS_VIEW, &identity);

And I'm trying to draw this:
Quote:

CustomVertex Triangle_Data[] = {
{-1.0f, -1.0f, 0.0f, D3DCOLOR_XRGB(255, 0, 0)},
{1.0f, -1.0, 0.0f, D3DCOLOR_XRGB(255, 0, 0)},
{-1.0f, 1.0f, 0.0f, D3DCOLOR_XRGB(255, 0, 0)},
{1.0f, 1.0f, 0.0f, D3DCOLOR_XRGB(255, 0, 0)}
};

...as a triangle strip, and I'm still seeing nothing :/

Share this post


Link to post
Share on other sites
Personally I didn’t have much success with ortho calls. It was never acting as I expected, and since I’m not a math major, I’m sure I was doing something wrong. However, over the years I’ve found it’s best to manage the projection, camera, and object placement yourself. Try the following and maybe it’ll help you to:

1. For projection use this any time the window size changes:

#define FOVDELTA 4 // sometimes I use 2 to get a wider angle
RECT rec=pGame->GetWinBoundRect();
FLOAT fAspect = (rec.right - rec.left)/(rec.bottom - rec.top);
D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/FOVDELTA, fAspect, 0.10f, 100000.0f );
m_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );


2. To set an objects location before it’s rendered do this:

m_pd3dDevice->SetTransform( D3DTS_WORLD, matObject );

realize however, that matObject should be a 4x4 matrix containing the objects position and orientation information. Let me know if you need more details on this.

The objects location should be relative to it’s parent. If it’s parent is the WORLD then leave it as it is. Oh, assuming your world matches the IDENTITY matrix, you’ll want your matObject initialized to that before you start.

However, if your object is say a weapon in a characters hand, the weapon itself is probably modeled from 0,0,0 with all the vertices being relative to it. Then the weapon is placed in a characters hand, so the weapon is relative to the character. The character might be relative to the WORLD or the character might be inside a building in which case they are relative to the building. Therefore, assuming you have a copy of the parent matrix (already adjusted for its location in the world) to put the weapon into the players hand, the location of the weapon would be relative to the character, not the world. To do this multiply the weapon matrix to the character matrix before setting the WORLD transform. Ie: D3DXMatrixMultiply ( &matNew, &matWeapon, &matParent );

That last paragraph was probably confusing, but in short, it’s like this.

- If the players hand is 1 unit from the players center point
- If the player is standing at 138,768,400
- You might think the weapon needs to be 1 unit greater (at the hand)
- Therefore you might put the weapon at 139,769,401 (os something like that)
- Instead however, you should put the weapon at 1,1,1 (or whatever)
- Since you’ll multiply the 1,1,1 by the 138,768,400, it’ll provide a new matrix with 139,769,401 for you.
- What this also provides is management for the orientation, so if the character turns the weapon is still relative to the characters new position, so you don’t need to also turn the weapon. The weapon stays at the orientation it was at (probably straight ahead) and when multiplied to the character it’ll take on the correct orientation

3. Set the camera (probably your main players character matrix for FPS):

D3DXMATRIX matNew;
D3DXMATRIX matInvert;

// The camera is relative to the terrain object it is over
D3DXMatrixMultiply ( &matNew, &matCamera, &matParent );

// Set the VIEW MATRIX TO THE INVERT OF THE CAMERA
// In 3D we really draw everything the opposite of what we think
// If the player moves left in the scene, we really shift everything
// else right, hence, INVERT the camera before drawing
MU3DMath_MatrixInvert(matInvert, matNew );
m_pd3dDevice->SetTransform( D3DTS_VIEW, &matInvert );

What’s key here, is two things.

a. like the weapon, the players is probably relative to something else, maybe inside a building or inside a moving vehicle, so you want to multiply it to the parent, just like we did the weapon
b. If the players turns right, we don’t move the camera right. The players turns right, but at render time we really turn everything else left, hence, the call to MatrixInvert, then set the View transform.

Hope this helps.

QUAD







Share this post


Link to post
Share on other sites
Did you check the vertex-order? (I mean clockwise or counter-clockwise). Maybe try drawing a standard trianglelist first?

edit:
I see your znear is 0. Maybe try putting it at 1.0, and zfar at 10.0 and then put the z-coordinates of all vertices at 5.0
This probably shouldn't matter for an ortho projection, but you never know...
I'm only guessing here :)

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
has anyone used an otho matrix in a real situation. I have to scale the width and height by the depth.

Vector3 p = cam->GetPos();p.y=0;p.x=0;
float zoom = (Vector3(0) - p).Length()/cam->GetFar();
D3DXMatrixOrthoLH((D3DXMATRIX*)&mProjMat,width*zoom,height*zoom
,cam->GetNear(),cam->GetFar());

I know this is i rigjob but I'm not sure why it eon't zoom in without it.
where's the real info on how to make an ortho projection?

Share this post


Link to post
Share on other sites

This topic is 4554 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.

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