]> git.lizzy.rs Git - shadowclad.git/blob - src/engine/geometry.c
Calculate face normals from vertices
[shadowclad.git] / src / engine / geometry.c
1 #include "geometry.h"
2
3 #include <math.h>
4 #include <stddef.h>
5
6 const float TAU = 6.28318530718f;
7
8
9
10 Transform identity() {
11         return (Transform) { .a1 = 1.0f, .a2 = 0.0f, .a3 = 0.0f, .a4 = 0.0f,
12                              .b1 = 0.0f, .b2 = 1.0f, .b3 = 0.0f, .b4 = 0.0f,
13                              .c1 = 0.0f, .c2 = 0.0f, .c3 = 1.0f, .c4 = 0.0f,
14                              .d1 = 0.0f, .d2 = 0.0f, .d3 = 0.0f, .d4 = 1.0f };
15 }
16
17 Transform multiply(Transform t1, Transform t2) {
18         GLfloat* a = (GLfloat*) &t1;
19         GLfloat* b = (GLfloat*) &t2;
20         Transform result;
21         GLfloat* c = (GLfloat*) &result;
22
23         for (size_t row = 0; row < 4; ++row) {
24                 for (size_t col = 0; col < 4; ++col) {
25                         c[(row * 4) + col] =
26                                 a[(row * 4) + 0] * b[(0 * 4) + col]
27                                 + a[(row * 4) + 1] * b[(1 * 4) + col]
28                                 + a[(row * 4) + 2] * b[(2 * 4) + col]
29                                 + a[(row * 4) + 3] * b[(3 * 4) + col];
30                 }
31         }
32         return result;
33 }
34
35 void translate(Transform* transform, Vector3D vec) {
36         *transform = multiply(
37                 (Transform) { .a1 = 1.0f, .a2 = 0.0f, .a3 = 0.0f, .a4 = vec.x,
38                               .b1 = 0.0f, .b2 = 1.0f, .b3 = 0.0f, .b4 = vec.y,
39                               .c1 = 0.0f, .c2 = 0.0f, .c3 = 1.0f, .c4 = vec.z,
40                               .d1 = 0.0f, .d2 = 0.0f, .d3 = 0.0f, .d4 = 1.0f },
41                 *transform);
42 }
43
44 void rotate(Transform* transform, Vector3D axis, float angle) {
45         axis = normalized(axis);
46         float l = axis.x;
47         float m = axis.y;
48         float n = axis.z;
49         float sinA = sinf(angle);
50         float cosA = cosf(angle);
51         float omcA = 1 - cosA;
52
53         *transform = multiply(
54                 (Transform) { l*l*omcA + cosA, m*l*omcA - n*sinA, n*l*omcA + m*sinA, 0.0f,
55                               l*m*omcA + n*sinA, m*m*omcA + cosA, n*m*omcA - l*sinA, 0.0f,
56                               l*n*omcA - m*sinA, m*n*omcA + l*sinA, n*n*omcA + cosA, 0.0f,
57                               0.0f, 0.0f, 0.0f, 1.0f },
58                 *transform);
59 }
60
61 Vector3D addVectors(Vector3D v1, Vector3D v2){
62         return (Vector3D) { v1.x + v2.x, v1.y + v2.y, v1.z + v2.z };
63 }
64
65 Vector3D subtractVectors(Vector3D v1, Vector3D v2) {
66         return (Vector3D) { v1.x - v2.x, v1.y - v2.y, v1.z - v2.z };
67 }
68
69 Vector3D crossProduct(Vector3D v1, Vector3D v2) {
70         return (Vector3D) { .x = (v1.y * v2.z) - (v1.z * v2.y),
71                             .y = (v1.z * v2.x) - (v1.x * v2.z),
72                             .z = (v1.x * v2.y) - (v1.y * v2.x) };
73 }
74
75 Vector3D applyTransform(Transform transform, Vector3D vec) {
76         GLfloat* a = (GLfloat*) &transform;
77         GLfloat b[4] = { vec.x, vec.y, vec.z, 1.0f };
78         GLfloat c[4];
79
80         for (size_t row = 0; row < 4; ++row) {
81                 c[row] =
82                         a[(row * 4) + 0] * b[0]
83                         + a[(row * 4) + 1] * b[1]
84                         + a[(row * 4) + 2] * b[2]
85                         + a[(row * 4) + 3] * b[3];
86         }
87         return (Vector3D) { c[0], c[1], c[2] };
88 }
89
90 Vector3D translationOf(Transform transform) {
91         return (Vector3D) { transform.a4, transform.b4, transform.c4 };
92 }
93
94 Vector3D normalized(Vector3D vec) {
95         float magnitude = sqrtf(vec.x * vec.x + vec.y * vec.y + vec.z * vec.z);
96         return (Vector3D) {vec.x / magnitude, vec.y / magnitude, vec.z / magnitude};
97 }