0

I've been working on my own 3D Engine using Direct3D. This went pretty good, until I ran into an issue with the World View and Projection Matrices. I'am using code from previous projects that I worked, but doesn't in the project. So I decided to use the Direct3D functions D3DXMatrixLookAtLH and D3DXMatrixPerspectiveFovLH.

This gives a working matrices, but if by rotating or translating the camera I move geometry close to the edge of the screen, it stretches that entire object in the horizontal axis, now i'm not sure if this is correct or not.

Cube in the middle of the screen looks normal: Normal Cube

But if I move it to the side it starts to stretch: Stretched cube

This is the View matrix that I get in such a case:

-0.81964797 -0.017183444    -0.57260966 0.00000000
 0.00000000  0.99954993 -0.029995499    0.00000000
 0.57286739 -0.024585750    -0.81927919 0.00000000
-1.1457349   0.049171507     1.6385586  1.0000000

I also noticed that between the WVP matrix in the application and the matrix the shader receives it gets transposed. ( I use memcpy to get it in the CBuffer, so that shouldn't be the problem) This is not a major issue, I just transpose it before it gets send, but I would like to know if this is common.

this is my shader:

cbuffer WVP :cb0
{
    float4x4 WVP;
};


struct VOut
{
    float4 position : SV_POSITION;
    float4 color : COLOR;
};

VOut VShader(float3 position : POSITION, float4 color : COLOR)
{
    VOut output;

    output.position = mul( float4(position, 1.0f), WVP);

    output.color = color;

    return output;
}


float4 PShader(float4 position : SV_POSITION, float4 color : COLOR) : SV_TARGET
{
    return color;
}

This is the code in that happens every frame to update the View matrix according to input:

// reset the vectors so the changes don't stack
vcPos.Set(x, y, z);
vcDir.Set(0.0f, 0.0f, -1.0f);

// Rotate the dir vector
Matrix3D m;
m.Rota(Looky/100, 0.0f, Lookx/100);
vcDir.RotateWith(m);

// add the pos to the dir vector so it points to in a direction rather then a point in the world
vcDir += vcPos;

// Set and get the View matrix
g_pDevice->SetViewMatrix(vcRight, vcUp, vcDir, vcPos );
g_pDevice->GetViewProjMatrix(&g_mView, NULL);

// Multiply them
g_mWVP = g_mWorld * g_mView * g_mProj;

// Transpose them so the shader tranposes them back.
Transpose(&g_mWVP);

And this is the behind the scenes part of it:

View:

D3DXMatrixLookAtLH(&m_mView, &D3DXVECTOR3(vcPos.x, vcPos.y, vcPos.z),
                    &D3DXVECTOR3(vcDir.x, vcDir.y, vcDir.z), &D3DXVECTOR3(vcUp.x, vcUp.y, vcUp.z));   // The .x/.y/.z has to do with some compatability stuff 

Proj:

D3DXMatrixPerspectiveFovLH(&m_mProj, FOV, Aspect, m_fNear, m_fFar); // Straight 
forward

D3DXMatrixPerspectiveFovLH(&m_mProj, 90.0, Aspect, 0.1f, 100.0f); // With values

Update2: Complete rewrite with new information

Update3: I'm having problems with the View matrix and maybe the Projection. The World matrix works fine.

Update4:

After changing some more code, I now have something that seems to be working! The only Problem I have right now is the stretching to the side.

Stardidi
  • 308
  • 2
  • 10
  • I think the code that is setting up & modifying your Model/World, View and Projection matrices is probably more pertinent that your pixel shader code – Necrolis Jun 23 '12 at 14:53
  • @Necrolis Added the code, I added the shader code for the final matrix getting transposed – Stardidi Jun 23 '12 at 20:23

2 Answers2

0

Are you making sure to take the order you are multiplying translation matrices into account? what i mean is that if you first translate, then scale, the result will be a stretched mesh. You have to make sure to do them in order. If you want a mesh to spin around its own axis, you want to rotate first then translate. if you want the mesh to "orbit" around something, you first need to translate it the distance it will orbit around the object, then rotate, then translate it to that objects position.

Anyway, you mentioned stretching, so i'm guessing it might be because you are translating first then scaling:

worldMatrix = translate * scale; // This will cause your mesh to stretch

worldMatrix = scale * translate; // this will cause your mesh to scale correctly

The only time you want to translate first is when you are NOT scaling, and you want your object to "orbit" around another object

iedoc
  • 2,266
  • 3
  • 30
  • 53
  • Well the World matrix works fine. Both translation and rotation ( haven't tested/used scaling yet) I'm right now trying to get the View matrix to work. So camera translation and rotation. And there is my problem. – Stardidi Jun 13 '12 at 20:38
  • Also, i'm using Direct3D's functions so I don't expect that to be an issue. – Stardidi Jun 23 '12 at 13:05
0

Note that the vertical stretch is perhaps not more than I would expect if the front of the object is nearer the camera. Are you sure that this output is incorrect?

But, more relevantly, I would look at tweaking your FoV parameter. And why, exactly, are you transposing it? If you use D3DXMATRIX, then the matrix will already be in the correct order to send to the GPU and does not need transposing.

Puppy
  • 144,682
  • 38
  • 256
  • 465
  • I don't feel like you really read my question :( I'm transposing it because otherwise I get really weird results, and this way the final WVP is the matrix that the shader receives, like I said, the matrix gets transposed somewhere between my final transpose and the calculation in the shader. I'm also not using D3DXMATRIX because I want my Engine to be API independent. My FOV is 90.0f and changing this gives expected results ( Zoom in/out) – Stardidi Jun 24 '12 at 09:01