So I seem to have made somewhat of a mess with 3D coordinates and rotations between my code, D3D11 and Bullet, and want to try and get back to having a common understanding of the maths involved (not try this, ok wrong, try inveresing the yaw passed to an API, etc.).
How I logically have various parts of the game currently setup
- +x is east
- +y is up
- +z is north
- a yaw of 0 is facing north
- yaw goes clockwise, so north, east, south, west, north (so same as compass bearings)
- pitch, not really sure, 0 is obviously flat, from there positive seems to be down
And so with D3D11 my matrices are
XMMATRIX xmproj = XMMatrixPerspectiveFovLH(fov, aspectRatio, near, far);
XMMATRIX xmview;
xmview = XMMatrixTranslation(-x, -y, -z);
xmview *= XMMatrixRotationY(-yaw);
xmview *= XMMatrixRotationX(-pitch);
XMMATRIX xmviewProj = xmview * xmproj;
//...multiply with world matrix as needed, can also use xmproj and xmview as is for DirectX::BoundingFrustum
xmShaderTransform = XMMatrixTranspose(xmShaderTransform);
//store in constant buffer for shader output.pos = mul(input.pos, transform)
So far so good, things seem to render as expected fine, but then once looking at logic...
Vector3F Camera::getForwardVec()const
{
auto c = std::cosf(-pitch);
Vector3F facing(
c * std::sinf(yaw),
std::sinf(-pitch),
c * std::cosf(yaw));
return facing;
}
Vector2F Player::getMovementVec(Vector2F move)const
{
//move is such that +z is forward, +x is strafe right
//only rotates on XZ plane (pitch is camera only and slopes/steps handled later)
auto c = std::cosf(-yaw);
auto s = std::sinf(-yaw);
return Vector2F(moveX * c - moveZ * s, moveX * s + moveZ * c);
}
...drawing some object...
btTransform transform;
motionstate.getworldTransform(transform);
XMFLOAT4X4 world;
transform.getOpenGLMatrix((float&)world.m);
XMMATRIX xmworld = XMLoadFloat4x4(&world);
XMMATRIX xmmatrix = xmworld * xmviewProj;
xmmatrix = XMMatrixTranspose(xmmatrix);
//use xmmatrix in shader
I am really not happy with having to have the -yaw and -pitch there to make those work... I also get a similar thing with my currently simple integration with bullet, e.g. I have to pass -yaw as the rotation to ghost object for my btKinematicCharacterController, yet if I use the Bullet getOpenGLMatrix to get a world matrix and then do "world * view * proj" I seem to get correct results?
Are those to be expected, I am kind of feeling I stuffed something up somewhere, especially with how I am handling yaw? But simply saying it goes the other way I am still not sure is correct (and leaves -yaw in getForwardVec instead...), since that changes the view matrix, and on the grounds that I am "rotating the world around the camera" being my understanding there, an inverse value makes sense (rotate the entire world counterclockwise rather than the screen/camera clockwise)...