Skip to content

Commit a733a68

Browse files
committed
Changed matrix mult. to match D3D convention
i.e. vectors are rows: v' = v * M1 * M2
1 parent c52ef9a commit a733a68

File tree

13 files changed

+398
-412
lines changed

13 files changed

+398
-412
lines changed

07. Virtual Camera/3DMaths.h

+63-65
Original file line numberDiff line numberDiff line change
@@ -18,43 +18,43 @@ struct float4
1818
float x, y, z, w;
1919
};
2020

21-
struct float4x4
21+
union float4x4
2222
{
23-
// Stored in column major, access with [col][row]
2423
float m[4][4];
24+
float4 cols[4];
25+
26+
inline float4 row(int i) { // Returns i-th row of matrix
27+
return { m[0][i], m[1][i], m[2][i], m[3][i] };
28+
}
2529
};
2630

27-
inline float degreesToRadians(float degs)
28-
{
31+
inline float degreesToRadians(float degs) {
2932
return degs * ((float)M_PI / 180.0f);
3033
}
3134

32-
inline float length(float3 v)
33-
{
35+
inline float length(float3 v) {
3436
float result = sqrtf(v.x*v.x + v.y*v.y + v.z*v.z);
3537
return result;
3638
}
3739

38-
inline float3 operator* (float3 v, float f)
39-
{
40-
float3 result = {v.x*f, v.y*f, v.z*f};
41-
return result;
40+
inline float dot(float4 a, float4 b) {
41+
return a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w;
4242
}
4343

44-
inline float3 normalise(float3 v)
45-
{
46-
float invLength = 1.f / length(v);
47-
float3 result = v * invLength;
48-
return result;
44+
inline float3 operator* (float3 v, float f) {
45+
return {v.x*f, v.y*f, v.z*f};
4946
}
5047

51-
inline float3 cross(float3 a, float3 b)
52-
{
53-
float3 result;
54-
result.x = ((a.y * b.z) - (a.z * b.y));
55-
result.y = ((a.z * b.x) - (a.x * b.z));
56-
result.z = ((a.x * b.y) - (a.y * b.x));
57-
return result;
48+
inline float3 normalise(float3 v) {
49+
return v * (1.f / length(v));
50+
}
51+
52+
inline float3 cross(float3 a, float3 b) {
53+
return {
54+
a.y*b.z - a.z*b.y,
55+
a.z*b.x - a.x*b.z,
56+
a.x*b.y - a.y*b.x
57+
};
5858
}
5959

6060
inline float3 operator+= (float3 &lhs, float3 rhs) {
@@ -71,49 +71,40 @@ inline float3 operator-= (float3 &lhs, float3 rhs) {
7171
return lhs;
7272
}
7373

74-
inline float3 operator- (float3 v)
75-
{
76-
float3 result = {-v.x, -v.y, -v.z};
77-
return result;
74+
inline float3 operator- (float3 v) {
75+
return {-v.x, -v.y, -v.z};
7876
}
7977

8078
inline float4x4 rotateXMat(float rad) {
81-
float4x4 result = {};
8279
float sinTheta = sinf(rad);
8380
float cosTheta = cosf(rad);
84-
result.m[0][0] = 1.f;
85-
result.m[1][1] = cosTheta;
86-
result.m[1][2] = sinTheta;
87-
result.m[2][1] = -sinTheta;
88-
result.m[2][2] = cosTheta;
89-
result.m[3][3] = 1.f;
90-
return result;
81+
return {
82+
1, 0, 0, 0,
83+
0, cosTheta, -sinTheta, 0,
84+
0, sinTheta, cosTheta, 0,
85+
0, 0, 0, 1
86+
};
9187
}
9288

9389
inline float4x4 rotateYMat(float rad) {
94-
float4x4 result = {};
9590
float sinTheta = sinf(rad);
9691
float cosTheta = cosf(rad);
97-
result.m[0][0] = cosTheta;
98-
result.m[0][2] = -sinTheta;
99-
result.m[1][1] = 1.f;
100-
result.m[2][0] = sinTheta;
101-
result.m[2][2] = cosTheta;
102-
result.m[3][3] = 1.f;
103-
return result;
92+
return {
93+
cosTheta, 0, sinTheta, 0,
94+
0, 1, 0, 0,
95+
-sinTheta, 0, cosTheta, 0,
96+
0, 0, 0, 1
97+
};
10498
}
10599

106100
inline float4x4 translationMat(float3 trans)
107101
{
108-
float4x4 result = {};
109-
result.m[0][0] = 1.f;
110-
result.m[1][1] = 1.f;
111-
result.m[2][2] = 1.f;
112-
result.m[3][0] = trans.x;
113-
result.m[3][1] = trans.y;
114-
result.m[3][2] = trans.z;
115-
result.m[3][3] = 1.f;
116-
return result;
102+
return {
103+
1, 0, 0, trans.x,
104+
0, 1, 0, trans.y,
105+
0, 0, 1, trans.z,
106+
0, 0, 0, 1
107+
};
117108
}
118109

119110
inline float4x4 makePerspectiveMat(float aspectRatio, float fovYRadians, float zNear, float zFar)
@@ -130,23 +121,30 @@ inline float4x4 makePerspectiveMat(float aspectRatio, float fovYRadians, float z
130121
float4x4 result = {
131122
xScale, 0, 0, 0,
132123
0, yScale, 0, 0,
133-
0, 0, zScale, -1,
134-
0, 0, zTranslation, 0
124+
0, 0, zScale, zTranslation,
125+
0, 0, -1, 0
135126
};
136127
return result;
137128
}
138129

139130
inline float4x4 operator* (float4x4 a, float4x4 b)
140131
{
141-
float4x4 result = {};
142-
for(int col = 0; col < 4; ++col) {
143-
for(int row = 0; row < 4; ++row) {
144-
float sum = 0.0f;
145-
for(int i = 0; i < 4; ++i) {
146-
sum += b.m[col][i] * a.m[i][row];
147-
}
148-
result.m[col][row] = sum;
149-
}
150-
}
151-
return result;
152-
}
132+
return {
133+
dot(a.row(0), b.cols[0]),
134+
dot(a.row(1), b.cols[0]),
135+
dot(a.row(2), b.cols[0]),
136+
dot(a.row(3), b.cols[0]),
137+
dot(a.row(0), b.cols[1]),
138+
dot(a.row(1), b.cols[1]),
139+
dot(a.row(2), b.cols[1]),
140+
dot(a.row(3), b.cols[1]),
141+
dot(a.row(0), b.cols[2]),
142+
dot(a.row(1), b.cols[2]),
143+
dot(a.row(2), b.cols[2]),
144+
dot(a.row(3), b.cols[2]),
145+
dot(a.row(0), b.cols[3]),
146+
dot(a.row(1), b.cols[3]),
147+
dot(a.row(2), b.cols[3]),
148+
dot(a.row(3), b.cols[3]),
149+
};
150+
}

07. Virtual Camera/main.cpp

+50-50
Original file line numberDiff line numberDiff line change
@@ -395,9 +395,6 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPSTR /*lpC
395395
d3d11Device->CreateRasterizerState(&rasterizerDesc, &rasterizerState);
396396
}
397397

398-
// Game data
399-
float2 playerPos = {};
400-
401398
// Camera
402399
float3 cameraPos = {0, 0, 2};
403400
float3 cameraFwd = {0, 0, -1};
@@ -479,62 +476,65 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPSTR /*lpC
479476
}
480477

481478
// Update camera
482-
float3 camFwdXZ = normalise({cameraFwd.x, 0, cameraFwd.z});
483-
float3 cameraRightXZ = cross(camFwdXZ, {0, 1, 0});
484-
485-
const float CAM_MOVE_SPEED = 5.f; // in metres per second
486-
const float CAM_MOVE_AMOUNT = CAM_MOVE_SPEED * dt;
487-
if(global_keyIsDown[GameActionMoveCamFwd])
488-
cameraPos += camFwdXZ * CAM_MOVE_AMOUNT;
489-
if(global_keyIsDown[GameActionMoveCamBack])
490-
cameraPos -= camFwdXZ * CAM_MOVE_AMOUNT;
491-
if(global_keyIsDown[GameActionMoveCamLeft])
492-
cameraPos -= cameraRightXZ * CAM_MOVE_AMOUNT;
493-
if(global_keyIsDown[GameActionMoveCamRight])
494-
cameraPos += cameraRightXZ * CAM_MOVE_AMOUNT;
495-
if(global_keyIsDown[GameActionRaiseCam])
496-
cameraPos.y += CAM_MOVE_AMOUNT;
497-
if(global_keyIsDown[GameActionLowerCam])
498-
cameraPos.y -= CAM_MOVE_AMOUNT;
499-
500-
const float CAM_TURN_SPEED = M_PI; // in radians per second
501-
const float CAM_TURN_AMOUNT = CAM_TURN_SPEED * dt;
502-
if(global_keyIsDown[GameActionTurnCamLeft])
503-
cameraYaw += CAM_TURN_AMOUNT;
504-
if(global_keyIsDown[GameActionTurnCamRight])
505-
cameraYaw -= CAM_TURN_AMOUNT;
506-
if(global_keyIsDown[GameActionLookUp])
507-
cameraPitch += CAM_TURN_AMOUNT;
508-
if(global_keyIsDown[GameActionLookDown])
509-
cameraPitch -= CAM_TURN_AMOUNT;
510-
511-
// Wrap yaw to avoid floating-point errors if we turn too far
512-
while(cameraYaw >= 2*M_PI)
513-
cameraYaw -= 2*M_PI;
514-
while(cameraYaw <= -2*M_PI)
515-
cameraYaw += 2*M_PI;
516-
517-
// Clamp pitch to stop camera flipping upside down
518-
if(cameraPitch > degreesToRadians(85))
519-
cameraPitch = degreesToRadians(85);
520-
if(cameraPitch < -degreesToRadians(85))
521-
cameraPitch = -degreesToRadians(85);
479+
{
480+
float3 camFwdXZ = normalise({cameraFwd.x, 0, cameraFwd.z});
481+
float3 cameraRightXZ = cross(camFwdXZ, {0, 1, 0});
482+
483+
const float CAM_MOVE_SPEED = 5.f; // in metres per second
484+
const float CAM_MOVE_AMOUNT = CAM_MOVE_SPEED * dt;
485+
if(global_keyIsDown[GameActionMoveCamFwd])
486+
cameraPos += camFwdXZ * CAM_MOVE_AMOUNT;
487+
if(global_keyIsDown[GameActionMoveCamBack])
488+
cameraPos -= camFwdXZ * CAM_MOVE_AMOUNT;
489+
if(global_keyIsDown[GameActionMoveCamLeft])
490+
cameraPos -= cameraRightXZ * CAM_MOVE_AMOUNT;
491+
if(global_keyIsDown[GameActionMoveCamRight])
492+
cameraPos += cameraRightXZ * CAM_MOVE_AMOUNT;
493+
if(global_keyIsDown[GameActionRaiseCam])
494+
cameraPos.y += CAM_MOVE_AMOUNT;
495+
if(global_keyIsDown[GameActionLowerCam])
496+
cameraPos.y -= CAM_MOVE_AMOUNT;
497+
498+
const float CAM_TURN_SPEED = M_PI; // in radians per second
499+
const float CAM_TURN_AMOUNT = CAM_TURN_SPEED * dt;
500+
if(global_keyIsDown[GameActionTurnCamLeft])
501+
cameraYaw += CAM_TURN_AMOUNT;
502+
if(global_keyIsDown[GameActionTurnCamRight])
503+
cameraYaw -= CAM_TURN_AMOUNT;
504+
if(global_keyIsDown[GameActionLookUp])
505+
cameraPitch += CAM_TURN_AMOUNT;
506+
if(global_keyIsDown[GameActionLookDown])
507+
cameraPitch -= CAM_TURN_AMOUNT;
508+
509+
// Wrap yaw to avoid floating-point errors if we turn too far
510+
while(cameraYaw >= 2*M_PI)
511+
cameraYaw -= 2*M_PI;
512+
while(cameraYaw <= -2*M_PI)
513+
cameraYaw += 2*M_PI;
514+
515+
// Clamp pitch to stop camera flipping upside down
516+
if(cameraPitch > degreesToRadians(85))
517+
cameraPitch = degreesToRadians(85);
518+
if(cameraPitch < -degreesToRadians(85))
519+
cameraPitch = -degreesToRadians(85);
520+
}
522521

523522
// Calculate view matrix from camera data
524523
//
525-
// float4x4 viewMat = inverse(translationMat(cameraPos) * rotateYMat(cameraYaw) * rotateXMat(cameraPitch));
524+
// float4x4 viewMat = inverse(rotateXMat(cameraPitch) * rotateYMat(cameraYaw) * translationMat(cameraPos));
526525
// NOTE: We can simplify this calculation to avoid inverse()!
527526
// Applying the rule inverse(A*B) = inverse(B) * inverse(A) gives:
528-
// float4x4 viewMat = inverse(rotateXMat(cameraPitch)) * inverse(rotateYMat(cameraYaw)) * inverse(translationMat(cameraPos));
527+
// float4x4 viewMat = inverse(translationMat(cameraPos)) * inverse(rotateYMat(cameraYaw)) * inverse(rotateXMat(cameraPitch));
529528
// The inverse of a rotation/translation is a negated rotation/translation:
530-
float4x4 viewMat = rotateXMat(-cameraPitch) * rotateYMat(-cameraYaw) * translationMat(-cameraPos);
531-
cameraFwd = {viewMat.m[2][0], viewMat.m[2][1], -viewMat.m[2][2]};
529+
float4x4 viewMat = translationMat(-cameraPos) * rotateYMat(-cameraYaw) * rotateXMat(-cameraPitch);
530+
// Update the forward vector we use for camera movement:
531+
cameraFwd = {viewMat.m[0][2], viewMat.m[1][2], -viewMat.m[2][2]};
532532

533533
// Spin the quad
534-
float4x4 modelMat = rotateYMat(0.3f * (float)(M_PI * currentTimeInSeconds));
534+
float4x4 modelMat = rotateYMat(0.2f * (float)(M_PI * currentTimeInSeconds));
535535

536-
// Copy model-view-projection matrix to uniform buffer
537-
float4x4 modelViewProj = perspectiveMat * viewMat * modelMat;
536+
// Calculate model-view-projection matrix to send to shader
537+
float4x4 modelViewProj = modelMat * viewMat * perspectiveMat;
538538

539539
// Update constant buffer
540540
D3D11_MAPPED_SUBRESOURCE mappedSubresource;

07. Virtual Camera/shaders.hlsl

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ SamplerState mysampler : register(s0);
2020
VS_Output vs_main(VS_Input input)
2121
{
2222
VS_Output output;
23-
output.pos = mul(modelViewProj, float4(input.pos, 0.0f, 1.0f));
23+
output.pos = mul(float4(input.pos, 0.0f, 1.0f), modelViewProj);
2424
output.uv = input.uv;
2525
return output;
2626
}

0 commit comments

Comments
 (0)