]> git.lizzy.rs Git - shadowclad.git/blob - src/engine/scene.c
Finish moving to scene tree implementation; clean up unused code
[shadowclad.git] / src / engine / scene.c
1 #include <stdlib.h>
2
3 #include "engine/logger.h"
4
5 #include "scene.h"
6
7 Scene* currentScene = NULL;
8
9
10
11 Transform identity() {
12         return (Transform) { .a1 = 1.0f, .a2 = 0.0f, .a3 = 0.0f, .a4 = 0.0f,
13                              .b1 = 0.0f, .b2 = 1.0f, .b3 = 0.0f, .b4 = 0.0f,
14                              .c1 = 0.0f, .c2 = 0.0f, .c3 = 1.0f, .c4 = 0.0f,
15                              .d1 = 0.0f, .d2 = 0.0f, .d3 = 0.0f, .d4 = 1.0f };
16 }
17
18 void multiply(Transform* transform, Transform by) {
19         GLfloat* a = (GLfloat*) &by;
20         GLfloat* b = (GLfloat*) transform;
21
22         for (size_t row = 0; row < 4; ++row) {
23                 for (size_t col = 0; col < 4; ++col) {
24                         b[(row * 4) + col] =
25                                 a[(row * 4) + 0] * b[(0 * 4) + col]
26                                 + a[(row * 4) + 1] * b[(1 * 4) + col]
27                                 + a[(row * 4) + 2] * b[(2 * 4) + col]
28                                 + a[(row * 4) + 3] * b[(3 * 4) + col];
29                 }
30         }
31 }
32
33 void translate(Transform* transform, Vector3D vec) {
34         multiply(transform, (Transform) { .a1 = 1.0f, .a2 = 0.0f, .a3 = 0.0f, .a4 = vec.x,
35                                       .b1 = 0.0f, .b2 = 1.0f, .b3 = 0.0f, .b4 = vec.y,
36                                       .c1 = 0.0f, .c2 = 0.0f, .c3 = 1.0f, .c4 = vec.z,
37                                       .d1 = 0.0f, .d2 = 0.0f, .d3 = 0.0f, .d4 = 1.0f });
38 }
39
40 Vector3D translationOf(Transform transform) {
41         return (Vector3D) { transform.a4, transform.b4, transform.c4 };
42 }
43
44 Scene* newScene() {
45         Scene* scene = malloc(sizeof(Scene));
46         *scene = (Scene) { .parent = NULL,
47                            .numChildren = 0u,
48                            .children = NULL,
49                            .transform = identity(),
50                            .solid = NULL };
51         return scene;
52 }
53
54 void insertChildScene(Scene* scene, Scene* newChild) {
55         if (!scene || !newChild) {
56                 return;
57         }
58         if (newChild->parent) {
59                 logError(
60                         "Cannot insert scene 0x%p as child of 0x%p, because it is already child of 0x%p",
61                         newChild,
62                         scene,
63                         newChild->parent);
64                 return;
65         }
66
67         scene->children = realloc(scene->children, ++(scene->numChildren) * sizeof(Scene*));
68         scene->children[scene->numChildren - 1] = newChild;
69
70         newChild->parent = scene;
71 }
72
73 void reparentScene(Scene* scene, Scene* newParent) {
74         if (!scene) {
75                 return;
76         }
77
78         if (scene->parent) {
79                 Scene* parent = scene->parent;
80                 size_t indexInParent = parent->numChildren;
81                 for (size_t i = 0; i < parent->numChildren; ++i) {
82                         if (parent->children[i] == scene) {
83                                 indexInParent = i;
84                                 break;
85                         }
86                 }
87                 // This includes the hopefully impossible case where parent->numChildren == 0
88                 if (indexInParent == parent->numChildren) {
89                         logError("Scene %p not found in children of parent %p", scene, parent);
90                 }
91                 else {
92                         for (size_t i = indexInParent; i < parent->numChildren - 1; ++i) {
93                                 parent->children[i] = parent->children[i + 1];
94                         }
95                         parent->children = realloc(parent->children, --(parent->numChildren) * sizeof(Scene*));
96                 }
97         }
98
99         scene->parent = NULL;
100
101         insertChildScene(newParent, scene);
102 }