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