]> git.localhorst.tv Git - blank.git/blob - src/model/model.cpp
linear model instance state
[blank.git] / src / model / model.cpp
1 #include "Model.hpp"
2 #include "Instance.hpp"
3 #include "Skeletons.hpp"
4
5 #include "Shape.hpp"
6 #include "ShapeRegistry.hpp"
7 #include "../app/TextureIndex.hpp"
8 #include "../graphics/DirectionalLighting.hpp"
9 #include "../graphics/EntityMesh.hpp"
10
11 #include <glm/gtx/quaternion.hpp>
12
13
14 namespace blank {
15
16 Instance::Instance()
17 : model(nullptr)
18 , state() {
19
20 }
21
22 void Instance::Render(const glm::mat4 &M, DirectionalLighting &prog) const {
23         model->RootPart().Render(M, state, prog);
24 }
25
26
27 Model::Model()
28 : id(0)
29 , root()
30 , part() {
31
32 }
33
34 void Model::Enumerate() {
35         part.clear();
36         part.resize(root.Enumerate(0), nullptr);
37         root.Index(part);
38 }
39
40 void Model::Instantiate(Instance &inst) const {
41         inst.model = this;
42         inst.state.clear();
43         inst.state.resize(part.size());
44 }
45
46
47 Part::Part()
48 : id(0)
49 , bounds{ glm::vec3(0.0f), glm::vec3(0.0f) }
50 , initial()
51 , mesh(nullptr)
52 , parent(nullptr)
53 , children() {
54
55 }
56
57 Part::~Part() {
58
59 }
60
61 Part &Part::AddChild() {
62         children.emplace_back();
63         children.back().parent = this;
64         return children.back();
65 }
66
67 std::uint16_t Part::Enumerate(std::uint16_t counter) noexcept {
68         id = counter++;
69         for (Part &part : children) {
70                 counter = part.Enumerate(counter);
71         }
72         return counter;
73 }
74
75 void Part::Index(std::vector<Part *> &index) noexcept {
76         index[id] = this;
77         for (Part &part : children) {
78                 part.Index(index);
79         }
80 }
81
82 glm::mat4 Part::LocalTransform(
83         const std::vector<State> &state
84 ) const noexcept {
85         glm::mat4 transform(toMat4(initial.orientation * state[id].orientation));
86         transform[3] = glm::vec4(initial.position + state[id].position, 1.0f);
87         return transform;
88 }
89
90 glm::mat4 Part::GlobalTransform(
91         const std::vector<State> &state
92 ) const noexcept {
93         if (parent) {
94                 return parent->GlobalTransform(state) * LocalTransform(state);
95         } else {
96                 return LocalTransform(state);
97         }
98 }
99
100 void Part::Render(
101         const glm::mat4 &M,
102         const std::vector<State> &state,
103         DirectionalLighting &prog
104 ) const {
105         glm::mat4 transform = M * LocalTransform(state);
106         if (mesh) {
107                 prog.SetM(transform);
108                 mesh->Draw();
109         }
110         for (const Part &part : children) {
111                 part.Render(transform, state, prog);
112         }
113 }
114
115
116 Skeletons::Skeletons()
117 : skeletons()
118 , meshes() {
119
120 }
121
122 Skeletons::~Skeletons() {
123
124 }
125
126 void Skeletons::LoadHeadless() {
127         skeletons.clear();
128         skeletons.reserve(4);
129         AABB bounds{{ -0.5f, -0.5f, -0.5f }, { 0.5f, 0.5f, 0.5f }};
130         {
131                 skeletons.emplace_back(new Model);
132                 skeletons[0]->ID(1);
133                 skeletons[0]->RootPart().bounds = bounds;
134                 skeletons[0]->Enumerate();
135         }
136         {
137                 skeletons.emplace_back(new Model);
138                 skeletons[1]->ID(2);
139                 skeletons[1]->RootPart().bounds = bounds;
140                 skeletons[1]->Enumerate();
141         }
142         {
143                 skeletons.emplace_back(new Model);
144                 skeletons[2]->ID(3);
145                 skeletons[2]->RootPart().bounds = bounds;
146                 skeletons[2]->Enumerate();
147         }
148         {
149                 skeletons.emplace_back(new Model);
150                 skeletons[3]->ID(4);
151                 skeletons[3]->RootPart().bounds = bounds;
152                 skeletons[3]->Enumerate();
153         }
154 }
155
156 void Skeletons::Load(const ShapeRegistry &shapes, TextureIndex &tex_index) {
157         LoadHeadless();
158         meshes.resize(4);
159         const Shape &shape = shapes.Get("player_head_block");
160         EntityMesh::Buffer buf;
161         std::vector<float> tex_map;
162         tex_map.push_back(tex_index.GetID("rock-1"));
163         tex_map.push_back(tex_index.GetID("rock-face"));
164         buf.Reserve(shape.VertexCount(), shape.IndexCount());
165         {
166                 shape.Fill(buf, tex_map);
167                 buf.hsl_mods.resize(shape.VertexCount(), { 0.0f, 1.0f, 1.0f });
168                 buf.rgb_mods.resize(shape.VertexCount(), { 1.0f, 1.0f, 0.0f });
169                 meshes[0].Update(buf);
170                 skeletons[0]->RootPart().mesh = &meshes[0];
171         }
172         {
173                 buf.Clear();
174                 shape.Fill(buf, tex_map);
175                 buf.hsl_mods.resize(shape.VertexCount(), { 0.0f, 1.0f, 1.0f });
176                 buf.rgb_mods.resize(shape.VertexCount(), { 0.0f, 1.0f, 1.0f });
177                 meshes[1].Update(buf);
178                 skeletons[1]->RootPart().mesh = &meshes[1];
179         }
180         {
181                 buf.Clear();
182                 shape.Fill(buf, tex_map);
183                 buf.hsl_mods.resize(shape.VertexCount(), { 0.0f, 1.0f, 1.0f });
184                 buf.rgb_mods.resize(shape.VertexCount(), { 1.0f, 0.0f, 1.0f });
185                 meshes[2].Update(buf);
186                 skeletons[2]->RootPart().mesh = &meshes[2];
187         }
188         {
189                 buf.Clear();
190                 shape.Fill(buf, tex_map);
191                 buf.hsl_mods.resize(shape.VertexCount(), { 0.0f, 1.0f, 1.0f });
192                 buf.rgb_mods.resize(shape.VertexCount(), { 1.0f, 0.25f, 0.5f });
193                 meshes[3].Update(buf);
194                 skeletons[3]->RootPart().mesh = &meshes[3];
195         }
196 }
197
198 Model *Skeletons::ByID(std::uint16_t id) noexcept {
199         if (id == 0 || id > skeletons.size()) {
200                 return nullptr;
201         } else {
202                 return skeletons[id - 1].get();
203         }
204 }
205
206 const Model *Skeletons::ByID(std::uint16_t id) const noexcept {
207         if (id == 0 || id > skeletons.size()) {
208                 return nullptr;
209         } else {
210                 return skeletons[id - 1].get();
211         }
212 }
213
214 }