]> git.lizzy.rs Git - shadowclad.git/blob - src/engine/geometry.c
Also yeah divide by zero is a thing
[shadowclad.git] / src / engine / geometry.c
1 /**
2  * Copyright 2018-2020 Iwo 'Outfrost' Bujkiewicz
3  *
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7  */
8
9 #include "geometry.h"
10
11 #include <math.h>
12 #include <stddef.h>
13
14 Transform identity() {
15         return (Transform) { .a1 = 1.0f, .a2 = 0.0f, .a3 = 0.0f, .a4 = 0.0f,
16                              .b1 = 0.0f, .b2 = 1.0f, .b3 = 0.0f, .b4 = 0.0f,
17                              .c1 = 0.0f, .c2 = 0.0f, .c3 = 1.0f, .c4 = 0.0f,
18                              .d1 = 0.0f, .d2 = 0.0f, .d3 = 0.0f, .d4 = 1.0f };
19 }
20
21 Transform multiply(Transform t1, Transform t2) {
22         GLfloat* a = (GLfloat*) &t1;
23         GLfloat* b = (GLfloat*) &t2;
24         Transform result;
25         GLfloat* c = (GLfloat*) &result;
26
27         for (size_t row = 0; row < 4; ++row) {
28                 for (size_t col = 0; col < 4; ++col) {
29                         c[(row * 4) + col] =
30                                 a[(row * 4) + 0] * b[(0 * 4) + col]
31                                 + a[(row * 4) + 1] * b[(1 * 4) + col]
32                                 + a[(row * 4) + 2] * b[(2 * 4) + col]
33                                 + a[(row * 4) + 3] * b[(3 * 4) + col];
34                 }
35         }
36         return result;
37 }
38
39 void translate(Transform* transform, Vector vec) {
40         *transform = multiply(
41                 (Transform) { .a1 = 1.0f, .a2 = 0.0f, .a3 = 0.0f, .a4 = vec.x,
42                               .b1 = 0.0f, .b2 = 1.0f, .b3 = 0.0f, .b4 = vec.y,
43                               .c1 = 0.0f, .c2 = 0.0f, .c3 = 1.0f, .c4 = vec.z,
44                               .d1 = 0.0f, .d2 = 0.0f, .d3 = 0.0f, .d4 = 1.0f },
45                 *transform);
46 }
47
48 void rotate(Transform* transform, Vector axis, float angle) {
49         axis = normalized(axis);
50         float l = axis.x;
51         float m = axis.y;
52         float n = axis.z;
53         float sinA = sinf(angle);
54         float cosA = cosf(angle);
55         float omcA = 1 - cosA;
56
57         *transform = multiply(
58                 (Transform) { l*l*omcA + cosA, m*l*omcA - n*sinA, n*l*omcA + m*sinA, 0.0f,
59                               l*m*omcA + n*sinA, m*m*omcA + cosA, n*m*omcA - l*sinA, 0.0f,
60                               l*n*omcA - m*sinA, m*n*omcA + l*sinA, n*n*omcA + cosA, 0.0f,
61                               0.0f, 0.0f, 0.0f, 1.0f },
62                 *transform);
63 }
64
65 Vector zeroVector() {
66         return (Vector) { 0.0f, 0.0f, 0.0f };
67 }
68
69 Vector addVectors(Vector v1, Vector v2) {
70         return (Vector) { v1.x + v2.x, v1.y + v2.y, v1.z + v2.z };
71 }
72
73 Vector subtractVectors(Vector v1, Vector v2) {
74         return (Vector) { v1.x - v2.x, v1.y - v2.y, v1.z - v2.z };
75 }
76
77 Vector crossProduct(Vector v1, Vector v2) {
78         return (Vector) { .x = (v1.y * v2.z) - (v1.z * v2.y),
79                           .y = (v1.z * v2.x) - (v1.x * v2.z),
80                           .z = (v1.x * v2.y) - (v1.y * v2.x) };
81 }
82
83 float dotProduct(Vector v1, Vector v2) {
84         return (v1.x * v2.x) + (v1.y * v2.y) + (v1.z * v2.z);
85 }
86
87 Vector scaleVector(Vector vec, float scale) {
88         return (Vector) { vec.x * scale,
89                           vec.y * scale,
90                           vec.z * scale };
91 }
92
93 Vector growVectorNoFlip(Vector vec, float amount) {
94         float mag = magnitude(vec);
95         float factor = (mag + amount) / mag;
96         if (factor < 0.0f) {
97                 factor = 0.0f;
98         }
99         return scaleVector(vec, factor);
100 }
101
102 Vector clampMagnitude(Vector vec, float maxMagnitude) {
103         float m = magnitude(vec);
104         if (m > maxMagnitude) {
105                 vec = scaleVector(vec, maxMagnitude / m);
106         }
107         return vec;
108 }
109
110 float magnitude(Vector vec) {
111         return sqrtf(vec.x * vec.x + vec.y * vec.y + vec.z * vec.z);
112 }
113
114 Vector applyTransform(Transform transform, Vector vec) {
115         GLfloat* a = (GLfloat*) &transform;
116         GLfloat b[4] = { vec.x, vec.y, vec.z, 1.0f };
117         GLfloat c[4];
118
119         for (size_t row = 0; row < 4; ++row) {
120                 c[row] =
121                         a[(row * 4) + 0] * b[0]
122                         + a[(row * 4) + 1] * b[1]
123                         + a[(row * 4) + 2] * b[2]
124                         + a[(row * 4) + 3] * b[3];
125         }
126         return (Vector) { c[0], c[1], c[2] };
127 }
128
129 Vector translationOf(Transform transform) {
130         return (Vector) { transform.a4, transform.b4, transform.c4 };
131 }
132
133 Vector normalized(Vector vec) {
134         float m = magnitude(vec);
135         if (m == 0.0f) {
136                 return zeroVector();
137         }
138         return (Vector) { vec.x / m, vec.y / m, vec.z / m };
139 }
140
141 float clamp(float x, float lower, float upper) {
142         return fmax(lower, fmin(upper, x));
143 }