🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Building View matrix

Started by
4 comments, last by ddlox 3 years, 6 months ago

Hi. I've recently started learning graphics programming using DirectX. I'm trying to implement a free camera and struggling with building the View matrix.

I'm using the left-hand coordinate system. The “up” vector is Z+, the “forward” vector is Y+, and if I'm not mistaken my X+ axis will be the left vector.

I'm initializing my "up", "forward" and "left" vectors accordingly. Then, I'm trying to build a view matrix with them but getting wrong results (I should see a cube in front of me and a floor under me, XMMatrixLookToLH solves the problems but I want to do it myself), I think I'm missing something in the cross product part. Could somebody help a noob? :)

  DirectX::XMVECTOR L = DirectX::XMLoadFloat3(&vLeftVector);
  DirectX::XMVECTOR U = DirectX::XMLoadFloat3(&vUpVector);
  DirectX::XMVECTOR F = DirectX::XMLoadFloat3(&vForwardVector);
  DirectX::XMVECTOR P = DirectX::XMLoadFloat3(&vLocation);


  F = DirectX::XMVector3Normalize(F);
  U = DirectX::XMVector3Normalize(DirectX::XMVector3Cross(L, F));
  L = DirectX::XMVector3Cross(F, U);


  float x = -DirectX::XMVectorGetX(DirectX::XMVector3Dot(P, L));
  float y = -DirectX::XMVectorGetX(DirectX::XMVector3Dot(P, F));
  float z = -DirectX::XMVectorGetX(DirectX::XMVector3Dot(P, U));

  DirectX::XMStoreFloat3(&vLeftVector, L);
  DirectX::XMStoreFloat3(&vUpVector, U);
  DirectX::XMStoreFloat3(&vForwardVector, F);

  mView(0, 0) = vLeftVector.x;
  mView(1, 0) = vLeftVector.y;
  mView(2, 0) = vLeftVector.z;
  mView(3, 0) = x;

  mView(0, 1) = vForwardVector.x;
  mView(1, 1) = vForwardVector.y;
  mView(2, 1) = vForwardVector.z;
  mView(3, 1) = y;

  mView(0, 2) = vUpVector.x;
  mView(1, 2) = vUpVector.y;
  mView(2, 2) = vUpVector.z;
  mView(3, 2) = z;

  mView(0, 3) = 0.0f;
  mView(1, 3) = 0.0f;
  mView(2, 3) = 0.0f;
  mView(3, 3) = 1.0f;

Advertisement

Flone said:
I want to do it myself

…so why are you asking us ? LOL

ok, if u look here: https://docs.microsoft.com/en-us/windows/win32/direct3d9/view-transform

u will see that:

  • the camera's UP vector is aligned with +Y axis (0,1,0) not +Z
  • the camera's FORWARD vector aligns with +Z and your left with +X

then when u look here, you will see how LookAt is put together:

https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixlookatlh

so from your calculation, it looks like you've got your nickers in a twist ?

try and do it like in the links and u'll be on yr way;

have fun ?

@ddlox Wait, the view matrix must describe the axes in world space, not view space, right? I've used LookAt with Z+ as “up” vector and it works fine. Now I'm using LookTo and it also works fine with Z+ as “up”, but I want to build the view matrix by myself. What you're describing is view space, but I don't need a view space, I need a view transform matrix.

Flone said:
the view matrix must describe the axes in world space

no

Flone said:
What you're describing is view space, but I don't need a view space, I need a view transform matrix.

what does the view transform matrix do? what is its purpose ?

@ddlox So, I reread my docs about view matrix and view space and I get what you're trying to tell me, I figured out that I had an issue in the matrix indeed, I fixed the problem, but... Now all my stuff is back facing (i.e. inverse), I've fixed it by adding a minus to all X (right-handed/left-handed mistake?), could you help me to understand why did this help?

My code now looks like this:

  DirectX::XMVECTOR R = DirectX::XMLoadFloat3(&vRightVector);
  DirectX::XMVECTOR U = DirectX::XMLoadFloat3(&vUpVector);
  DirectX::XMVECTOR F = DirectX::XMLoadFloat3(&vForwardVector);
  DirectX::XMVECTOR P = DirectX::XMLoadFloat3(&vLocation);


  F = DirectX::XMVector3Normalize(F);
  U = DirectX::XMVector3Normalize(DirectX::XMVector3Cross(R, F));
  R = DirectX::XMVector3Cross(F, U);


  float x = -DirectX::XMVectorGetX(DirectX::XMVector3Dot(P, R));
  float y = -DirectX::XMVectorGetX(DirectX::XMVector3Dot(P, F));
  float z = -DirectX::XMVectorGetX(DirectX::XMVector3Dot(P, U));

  DirectX::XMStoreFloat3(&vRightVector, R);
  DirectX::XMStoreFloat3(&vUpVector, U);
  DirectX::XMStoreFloat3(&vForwardVector, F);

  mView(0, 0) = -vRightVector.x;
  mView(1, 0) = -vRightVector.y;
  mView(2, 0) = -vRightVector.z;
  mView(3, 0) = -x;

  mView(0, 1) = vUpVector.x;
  mView(1, 1) = vUpVector.y;
  mView(2, 1) = vUpVector.z;
  mView(3, 1) = z;

  mView(0, 2) = vForwardVector.x;
  mView(1, 2) = vForwardVector.y;
  mView(2, 2) = vForwardVector.z;
  mView(3, 2) = y;

  mView(0, 3) = 0.0f;
  mView(1, 3) = 0.0f;
  mView(2, 3) = 0.0f;
  mView(3, 3) = 1.0f;

make sure:

// pseudo

compute the forward vector
F = V - P //  viewed point - camera position

then compute the right vector
Y = (0,1,0)	// use the +Y axis
R = Y * F // cross product from Y to F

then compute the up vector
U = F * R // from F to R

normalise the basis vectors R,U,F and insert them into the view matrix:

// pseudo
ViewMatrix4x4 =
[	R			U			F		0 	]
[	-Dot(R,P)		-Dot(U,P)		-Dot(F,P)	1	] 

one of the reasons, triangles appear reversed is due to the winding order and the handedness of your maths, so make sure that your triangle winding order is CW, like the pink triangle (https://cmichel.io/understanding-front-faces-winding-order-and-normals):

D3D11_RASTERIZER_DESC p;
...
p.FrontCounterClockwise = FALSE;
...

By negating like you did, you are forcing the rasterizer to accept that the camera is on the correct size of your triangles, instead the maths should work it out for u based on where it is ;

if you are going to try things by yourself like this, you need tutorials that do it from scratch as well not just ones which hide certain details;

https://www.gabrielgambetta.com/computer-graphics-from-scratch/introduction.html​

this is just one of them, there's more, but i leave it as an exercise for u to find out;

ok i hope this clarifies it a bit for you

that's it all the best ?

This topic is closed to new replies.

Advertisement