]> git.localhorst.tv Git - blank.git/blob - src/model/composite.cpp
basic message state
[blank.git] / src / model / composite.cpp
1 #include "CompositeModel.hpp"
2 #include "CompositeInstance.hpp"
3 #include "Skeletons.hpp"
4
5 #include "EntityModel.hpp"
6 #include "shapes.hpp"
7 #include "../graphics/DirectionalLighting.hpp"
8
9 #include <glm/gtx/quaternion.hpp>
10
11
12 namespace blank {
13
14 CompositeModel::CompositeModel()
15 : parent(nullptr)
16 , node_model(nullptr)
17 , id(0)
18 , bounds{{ 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f }}
19 , position(0.0f)
20 , orientation(1.0f, 0.0f, 0.0f, 0.0f)
21 , parts() {
22
23 }
24
25
26 CompositeModel &CompositeModel::AddPart() {
27         parts.emplace_back();
28         parts.back().parent = this;
29         return parts.back();
30 }
31
32
33 glm::mat4 CompositeModel::LocalTransform() const noexcept {
34         glm::mat4 transform(toMat4(orientation));
35         transform[3].x = position.x;
36         transform[3].y = position.y;
37         transform[3].z = position.z;
38         return transform;
39 }
40
41 glm::mat4 CompositeModel::GlobalTransform() const noexcept {
42         if (HasParent()) {
43                 return Parent().GlobalTransform() * LocalTransform();
44         } else {
45                 return LocalTransform();
46         }
47 }
48
49
50 void CompositeModel::Instantiate(CompositeInstance &inst) const {
51         inst.part_model = this;
52         inst.position = position;
53         inst.orientation = orientation;
54         inst.parts.clear();
55         inst.parts.reserve(parts.size());
56         for (const CompositeModel &part : parts) {
57                 part.Instantiate(inst.AddPart());
58         }
59 }
60
61
62 CompositeInstance::CompositeInstance()
63 : part_model(nullptr)
64 , parent(nullptr)
65 , position(0.0f)
66 , orientation(1.0f, 0.0f, 0.0f, 0.0f)
67 , parts() {
68
69 }
70
71
72 CompositeInstance &CompositeInstance::AddPart() {
73         parts.emplace_back();
74         parts.back().parent = this;
75         return parts.back();
76 }
77
78
79 glm::mat4 CompositeInstance::LocalTransform() const noexcept {
80         glm::mat4 transform(toMat4(orientation));
81         transform[3].x = position.x;
82         transform[3].y = position.y;
83         transform[3].z = position.z;
84         return transform;
85 }
86
87 glm::mat4 CompositeInstance::GlobalTransform() const noexcept {
88         if (HasParent()) {
89                 return Parent().GlobalTransform() * LocalTransform();
90         } else {
91                 return LocalTransform();
92         }
93 }
94
95
96 void CompositeInstance::Render(const glm::mat4 &M, DirectionalLighting &prog) const {
97         glm::mat4 transform(M * LocalTransform());
98         if (part_model->HasNodeModel()) {
99                 prog.SetM(transform);
100                 part_model->NodeModel().Draw();
101         }
102         for (const CompositeInstance &part : parts) {
103                 part.Render(transform, prog);
104         }
105 }
106
107
108 Skeletons::Skeletons()
109 : skeletons()
110 , models() {
111
112 }
113
114 Skeletons::~Skeletons() {
115
116 }
117
118 void Skeletons::LoadHeadless() {
119         skeletons.clear();
120         skeletons.reserve(4);
121         {
122                 AABB bounds{{ -0.5f, -0.5f, -0.5f }, { 0.5f, 0.5f, 0.5f }};
123                 skeletons.emplace_back(new CompositeModel);
124                 skeletons[0]->ID(1);
125                 skeletons[0]->Bounds(bounds);
126         }
127         {
128                 AABB bounds{{ -0.5f, -0.25f, -0.5f }, { 0.5f, 0.25f, 0.5f }};
129                 skeletons.emplace_back(new CompositeModel);
130                 skeletons[1]->ID(2);
131                 skeletons[1]->Bounds(bounds);
132         }
133         {
134                 AABB bounds{{ -0.25f, -0.5f, -0.25f }, { 0.25f, 0.5f, 0.25f }};
135                 skeletons.emplace_back(new CompositeModel);
136                 skeletons[2]->ID(3);
137                 skeletons[2]->Bounds(bounds);
138         }
139         {
140                 AABB bounds{{ -0.25f, -0.5f, -0.35f }, { 0.25f, 0.5f, 0.35f }};
141                 skeletons.emplace_back(new CompositeModel);
142                 skeletons[3]->ID(4);
143                 skeletons[3]->Bounds(bounds);
144         }
145 }
146
147 void Skeletons::Load() {
148         LoadHeadless();
149         models.resize(4);
150         EntityModel::Buffer buf;
151         {
152                 CuboidShape shape(skeletons[0]->Bounds());
153                 shape.Vertices(buf, 3.0f);
154                 buf.colors.resize(shape.VertexCount(), { 1.0f, 1.0f, 0.0f });
155                 models[0].Update(buf);
156                 skeletons[0]->SetNodeModel(&models[0]);
157         }
158         {
159                 CuboidShape shape(skeletons[1]->Bounds());
160                 buf.Clear();
161                 shape.Vertices(buf, 0.0f);
162                 buf.colors.resize(shape.VertexCount(), { 0.0f, 1.0f, 1.0f });
163                 models[1].Update(buf);
164                 skeletons[1]->SetNodeModel(&models[1]);
165         }
166         {
167                 StairShape shape(skeletons[2]->Bounds(), { 0.4f, 0.4f });
168                 buf.Clear();
169                 shape.Vertices(buf, 1.0f);
170                 buf.colors.resize(shape.VertexCount(), { 1.0f, 0.0f, 1.0f });
171                 models[2].Update(buf);
172                 skeletons[2]->SetNodeModel(&models[2]);
173         }
174         {
175                 CuboidShape shape(skeletons[3]->Bounds());
176                 buf.Clear();
177                 shape.Vertices(buf, 2.0f);
178                 buf.colors.resize(shape.VertexCount(), { 1.0f, 0.25f, 0.5f });
179                 models[3].Update(buf);
180                 skeletons[3]->SetNodeModel(&models[3]);
181         }
182 }
183
184 CompositeModel *Skeletons::ByID(std::uint16_t id) noexcept {
185         if (id == 0 || id > skeletons.size()) {
186                 return nullptr;
187         } else {
188                 return skeletons[id - 1].get();
189         }
190 }
191
192 const CompositeModel *Skeletons::ByID(std::uint16_t id) const noexcept {
193         if (id == 0 || id > skeletons.size()) {
194                 return nullptr;
195         } else {
196                 return skeletons[id - 1].get();
197         }
198 }
199
200 }