# Direct3D9 - D3DXVec3Project + WorldViewProj Matrix

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

## Recommended Posts

Hey,

First and foremost, I am not that familiar with the D3D scene of things (no pun intended), so all and any help would be appreciated.

I am currently working with a game which has a pure device, and this means that the buffered-state get functions fail, of course (i.e. GetTransform, GetViewport, etc.). Additionally, SetTransform does not get called, so I can't internally set a temporary variable to store the last known projection and view transformation matricies.

What I am trying to accomplish is to render a rectangle at a certain coordinate in the game. On non-pure devices, this is a very simple process, as I would just grab D3DTS_VIEW, D3DTS_PROJECTION, the viewport, an identity matrix, and the world coordinate, and throw them into the nice and friendly D3DXVec3Project function to get the screen space coordinate from the world coordinate.

However, in this particular game, I didn't have such luxuries. I read some articles online, where I discovered that the game is shader-based and that I could potentially grab the projection and view matricies from the shader registers. Here is an excerpt of the dump from the shader file which lists all of these registers:

 // Registers: // // Name Reg Size // ---------------- ----- ---- // gWorld c0 4 // gWorldViewProj c8 4 // gViewInverse c12 4 // globalScalars c39 1 // globalScalars2 c40 1 // gDayNightEffects c45 1 // globalAnimUV0 c208 1 // globalAnimUV1 c209 1 // 

Now, unlike some games, I now realized that there wasn't individual matricies, which could be passed into D3DXVec3Project. I assume the only one which I would need is the gWorldViewProj matrix (WorldViewProjection = World * View * Projection). The problem is what to do with it.

I also read that transforming that matrix using the point and the function D3DXVec3TransformCoord would NOT put it into screen coordinates: instead, it would put it into projection clip coordinates. Therefore, my best guess would be to somehow fit it into the D3DXVec3Project function.

Let's show some sample code to work off of:
 . . . // The location of the entity in the world where I want to draw the sprite on top of. D3DXVECTOR3 vecPosition(-100.5f, 1000.f, 15.f), vecOutput; . . . D3DVIEWPORT9 Viewport = {0, 0, 1920, 1080, 0, 1}; . . . // Grab the WorldViewProjection matrix from the shader buffer at register 8 as 4 float4's. D3DXMATRIX matWorldViewProj; pDevice->GetVertexShaderConstantF(8, matWorldViewProj, 4); . . . D3DXVec3Project(&vecOutput, &vecPosition, &Viewport, ???, ???, ???); 

This is really a learning experience for me, if anything. If and when it works, I can start playing around with the shader information (as I'm also new to that concept) and hopefully gain an appreciation for what's going on behind the scenes.

Do I have the right idea? Do I need to manually transform the matricies? Is this even possible, given my limitations?

Thanks again! Edited by ArterialCalamity

##### Share on other sites
A replacement for D3DXVec3Project does this:

[size="2"]math::matrix4 matComplete = matWorld * matView * matProjection;
[size="2"]matComplete.TransformCoord( vect );

[size="2"]vect.x = ( vect.x + 1.0f ) * viewPort.m_dwWidth * 0.5f + viewPort.m_dwX;
[size="2"]vect.y = ( 1.0f - vect.y ) * viewPort.m_dwHeight * 0.5f + viewPort.m_dwY;
[size="2"]vect.z = ( vect.z + 1.0f ) * 0.5f;

[size="2"]So basically, yes, you have all you need.

##### Share on other sites
Cool...very nice to know how that function works behind the scenes.

I still have a problem, though. By using the existing WorldViewProjection matrix with D3DXVec3Project, the position where the sprite is vastly incorrect (however, it still rendered at some random position depending on my camera angle). Currently I call the function as:

 D3DXMATRIX matWorldViewProj; GetVertexShaderConstantF(8, matWorldViewProj, 4); ... D3DXVec3Project(&vecOutput,&vecPosition,&Viewport,&matWorldViewProj, &matIdentity, &matIdentity);

I thought that my problem had to do with the fact that normally I would call the function as:

D3DXVec3Project(&vecOutput,&vecPosition,&Viewport,&matProj, &matView, &matIdentity);

...which would be calling D3DXVec3Project with a View * Projection matrix (since World is now an identity matrix). This is how I would call it in all other games to get the desired sprite position.

I thought I was going in the right direction when comparing this with previous methods, so then I noticed that there was a World matrix register (gWorld c0 4).

So I took the inverse of that and multiplied it with WorldViewProjection because (WorldViewProjection) x ([World][sup]-1[/sup]) = (ViewProjection).

I passed that to D3DXVec3Project, tested it in-game, and nothing rendered (the x and y positions were out of screen space (coordinates of 100000+ for x and y)).

I understand why the WorldViewProjection matrix didn't work, but now I'm confused what to do since my intuition also failed.

It sucks that I don't have a ViewProj matrix like most games to work off of. All I have is a ViewInv (inversed view) matrix, a WorldViewProj matrix, and a World matrix. Is there any way to put the matricies I have together and pass them into D3DVec3Project to get my desired result? :/ Edited by ArterialCalamity

##### Share on other sites
How does that Shader constant get calculated and set? Don't you have to have the three single matrices at one point?