SuperTuxKart
Loading...
Searching...
No Matches
sp_mesh_buffer.hpp
1// SuperTuxKart - a fun racing game with go-kart
2// Copyright (C) 2018 SuperTuxKart-Team
3//
4// This program is free software; you can redistribute it and/or
5// modify it under the terms of the GNU General Public License
6// as published by the Free Software Foundation; either version 3
7// of the License, or (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program; if not, write to the Free Software
16// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
18#ifndef HEADER_SP_MESH_BUFFER_HPP
19#define HEADER_SP_MESH_BUFFER_HPP
20
21#include "graphics/gl_headers.hpp"
22#include "graphics/sp/sp_base.hpp"
23#include "graphics/sp/sp_instanced_data.hpp"
24#include "graphics/sp/sp_per_object_uniform.hpp"
25#include "utils/types.hpp"
26
27#include <IMeshBuffer.h>
28#include <S3DVertex.h>
29
30#include <array>
31#include <cassert>
32#include <string>
33#include <tuple>
34#include <unordered_map>
35#include <vector>
36
37using namespace irr;
38using namespace scene;
39
40class Material;
41
42namespace SP
43{
44class SPShader;
45class SPTexture;
46
47class SPMeshBuffer : public IMeshBuffer, public SPPerObjectUniform
48{
49protected:
50 std::shared_ptr<SPShader> m_shaders[2];
51
52 std::vector<std::tuple<size_t/*first_index_id*/,
53 unsigned/*indices_count*/, Material*> > m_stk_material;
54
55 std::vector<std::array<std::shared_ptr<SPTexture>, 6> > m_textures;
56
57 std::unordered_map<std::string, unsigned> m_tex_cmp;
58
59 std::vector<video::S3DVertexSkinnedMesh> m_vertices;
60
61 GLuint m_ibo, m_vbo;
62
63 GLuint m_vao[DCT_FOR_VAO];
64
65 unsigned m_pitch;
66
67private:
68 std::vector<uint16_t> m_indices;
69
70 core::aabbox3d<f32> m_bounding_box;
71
72 std::vector<SPInstancedData> m_ins_dat[DCT_FOR_VAO];
73
74 void* m_ins_dat_mapped_ptr[DCT_FOR_VAO];
75
76 unsigned m_gl_instance_size[DCT_FOR_VAO];
77
78 GLuint m_ins_array[DCT_FOR_VAO];
79
80 bool m_uploaded_gl;
81
82 bool m_uploaded_instance;
83
84 bool m_skinned;
85
86 // ------------------------------------------------------------------------
87 bool initTexture();
88
89public:
91 {
92#ifdef _DEBUG
93 setDebugName("SMeshBuffer");
94#endif
95 m_stk_material.resize(1, std::make_tuple(0u, 0u, nullptr));
96
97 for (unsigned i = 0; i < DCT_FOR_VAO; i++)
98 {
99 m_ins_dat_mapped_ptr[i] = NULL;
100 m_gl_instance_size[i] = 0;
101 m_vao[i] = 0;
102 m_ins_array[i] = 0;
103 }
104
105 m_pitch = 0;
106 m_ibo = 0;
107 m_vbo = 0;
108 m_uploaded_gl = false;
109 m_uploaded_instance = false;
110 m_skinned = false;
111 }
112 // ------------------------------------------------------------------------
114 // ------------------------------------------------------------------------
115 virtual void draw(DrawCallType dct = DCT_NORMAL, int material_id = -1) const
116 {
117#ifndef SERVER_ONLY
118 glBindVertexArray(m_vao[dct]);
119 if (material_id == -1)
120 {
121 // Draw whole mesh buffer, usually in shadow pass
122 glDrawElementsInstanced(GL_TRIANGLES, getIndexCount(),
123 GL_UNSIGNED_SHORT, 0, (unsigned)m_ins_dat[dct].size());
124 }
125 else
126 {
127 glDrawElementsInstanced(GL_TRIANGLES,
128 std::get<1>(m_stk_material[material_id]),
129 GL_UNSIGNED_SHORT,
130 (void*)(std::get<0>(m_stk_material[material_id]) << 1),
131 (unsigned)m_ins_dat[dct].size());
132 }
133#endif
134 }
135 // ------------------------------------------------------------------------
136 virtual void uploadGLMesh();
137 // ------------------------------------------------------------------------
138 virtual void uploadInstanceData();
139 // ------------------------------------------------------------------------
140 bool combineMeshBuffer(SPMeshBuffer* spmb, bool different_material = true)
141 {
142 // We only use 16bit vertices
143 if (spmb->m_vertices.size() + m_vertices.size() > 65536)
144 {
145 return false;
146 }
147 const uint16_t old_vtx_count = (uint16_t)m_vertices.size();
148 m_vertices.insert(m_vertices.end(), spmb->m_vertices.begin(),
149 spmb->m_vertices.end());
150 for (uint16_t& idx : spmb->m_indices)
151 {
152 idx += old_vtx_count;
153 }
154 if (different_material)
155 {
156 m_stk_material.emplace_back(getIndexCount(), spmb->getIndexCount(),
157 std::get<2>(spmb->m_stk_material[0]));
158 }
159 else
160 {
161 std::get<1>(m_stk_material[0]) += (unsigned)spmb->m_indices.size();
162 }
163 m_indices.insert(m_indices.end(), spmb->m_indices.begin(),
164 spmb->m_indices.end());
165 return true;
166 }
167 // ------------------------------------------------------------------------
168 void initDrawMaterial();
169 // ------------------------------------------------------------------------
170 void enableSkinningData() { m_skinned = true; }
171 // ------------------------------------------------------------------------
172 Material* getSTKMaterial(unsigned first_index = 0) const
173 {
174 for (unsigned i = 0; i < m_stk_material.size(); i++)
175 {
176 if (i == unsigned(m_stk_material.size() - 1) ||
177 (first_index >= std::get<0>(m_stk_material[i]) &&
178 first_index < std::get<0>(m_stk_material[i + 1])))
179 {
180 return std::get<2>(m_stk_material[i]);
181 }
182 }
183 assert(false);
184 return NULL;
185 }
186 // ------------------------------------------------------------------------
187 void enableTextureMatrix(unsigned mat_id);
188 // ------------------------------------------------------------------------
189 std::array<std::shared_ptr<SPTexture>, 6>&
190 getSPTextures(unsigned first_index = 0)
191 {
192 assert(m_stk_material.size() == m_textures.size());
193 for (unsigned i = 0; i < m_stk_material.size(); i++)
194 {
195 if (i == unsigned(m_stk_material.size() - 1) ||
196 (first_index >= std::get<0>(m_stk_material[i]) &&
197 first_index < std::get<0>(m_stk_material[i + 1])))
198 {
199 return m_textures[i];
200 }
201 }
202 assert(false);
203 return m_textures[0];
204 }
205 // ------------------------------------------------------------------------
206 const std::array<std::shared_ptr<SPTexture>, 6>&
207 getSPTexturesByMaterialID(int material_id) const
208 {
209 assert((size_t)material_id < m_textures.size());
210 return m_textures[material_id];
211 }
212 // ------------------------------------------------------------------------
213 std::vector<Material*> getAllSTKMaterials() const
214 {
215 std::vector<Material*> ret;
216 for (unsigned i = 0; i < m_stk_material.size(); i++)
217 {
218 ret.push_back(std::get<2>(m_stk_material[i]));
219 }
220 return ret;
221 }
222 // ------------------------------------------------------------------------
223 const std::unordered_map<std::string, unsigned>& getTextureCompare() const
224 { return m_tex_cmp; }
225 // ------------------------------------------------------------------------
226 int getMaterialID(const std::string& tex_cmp) const
227 {
228 auto itr = m_tex_cmp.find(tex_cmp);
229 if (itr != m_tex_cmp.end())
230 {
231 return (int)itr->second;
232 }
233 return -1;
234 }
235 // ------------------------------------------------------------------------
236 void addInstanceData(const SPInstancedData& id, DrawCallType dct)
237 {
238 if (m_uploaded_instance)
239 {
240 for (unsigned i = 0; i < DCT_FOR_VAO; i++)
241 {
242 m_ins_dat[i].clear();
243 m_uploaded_instance = false;
244 }
245 }
246 m_ins_dat[dct].push_back(id);
247 }
248 // ------------------------------------------------------------------------
249 void recreateVAO(unsigned i);
250 // ------------------------------------------------------------------------
251 video::S3DVertexSkinnedMesh* getSPMVertex()
252 {
253 return m_vertices.data();
254 }
255 // ------------------------------------------------------------------------
256 void addSPMVertex(const video::S3DVertexSkinnedMesh& v)
257 {
258 m_vertices.push_back(v);
259 }
260 // ------------------------------------------------------------------------
261 void addIndex(uint16_t idx)
262 {
263 m_indices.push_back(idx);
264 }
265 // ------------------------------------------------------------------------
266 void setSPMVertices(std::vector<video::S3DVertexSkinnedMesh>& vertices)
267 {
268 m_vertices = std::move(vertices);
269 }
270 // ------------------------------------------------------------------------
271 void setIndices(std::vector<uint16_t>& indices)
272 {
273 m_indices = std::move(indices);
274 }
275 // ------------------------------------------------------------------------
276 void setSTKMaterial(Material* m);
277 // ------------------------------------------------------------------------
278 void reloadTextureCompare();
279 // ------------------------------------------------------------------------
280 void shrinkToFit()
281 {
282 m_vertices.shrink_to_fit();
283 m_indices.shrink_to_fit();
284 }
285 // ------------------------------------------------------------------------
286 SPShader* getShader(bool skinned = false) const
287 { return skinned ? m_shaders[1].get() : m_shaders[0].get(); }
288 // ------------------------------------------------------------------------
289 virtual const video::SMaterial& getMaterial() const
290 {
291 static video::SMaterial unused;
292 return unused;
293 }
294 // ------------------------------------------------------------------------
295 virtual video::SMaterial& getMaterial()
296 {
297 static video::SMaterial unused;
298 return unused;
299 }
300 // ------------------------------------------------------------------------
301 virtual const void* getVertices() const
302 {
303 return m_vertices.data();
304 }
305 // ------------------------------------------------------------------------
306 virtual void* getVertices()
307 {
308 return m_vertices.data();
309 }
310 // ------------------------------------------------------------------------
311 std::vector<video::S3DVertexSkinnedMesh>& getVerticesRef()
312 {
313 return m_vertices;
314 }
315 // ------------------------------------------------------------------------
316 virtual u32 getVertexCount() const
317 {
318 return (unsigned)m_vertices.size();
319 }
320 // ------------------------------------------------------------------------
321 virtual video::E_INDEX_TYPE getIndexType() const
322 {
323 return video::EIT_16BIT;
324 }
325 // ------------------------------------------------------------------------
326 std::vector<u16>& getIndicesRef()
327 {
328 return m_indices;
329 }
330 // ------------------------------------------------------------------------
331 virtual const u16* getIndices() const
332 {
333 return m_indices.data();
334 }
335 // ------------------------------------------------------------------------
336 virtual u16* getIndices()
337 {
338 return m_indices.data();
339 }
340 // ------------------------------------------------------------------------
341 virtual u32 getIndexCount() const
342 {
343 return (unsigned)m_indices.size();
344 }
345 // ------------------------------------------------------------------------
346 virtual const core::aabbox3d<f32>& getBoundingBox() const
347 {
348 return m_bounding_box;
349 }
350 // ------------------------------------------------------------------------
351 virtual void setBoundingBox(const core::aabbox3df& box)
352 {
353 m_bounding_box = box;
354 }
355 // ------------------------------------------------------------------------
356 virtual void recalculateBoundingBox()
357 {
358 if (m_vertices.empty())
359 {
360 m_bounding_box.reset(0.0f, 0.0f, 0.0f);
361 }
362 else
363 {
364 m_bounding_box.reset(m_vertices[0].m_position);
365 for (u32 i = 1; i < m_vertices.size(); i++)
366 {
367 m_bounding_box.addInternalPoint(m_vertices[i].m_position);
368 }
369 }
370 }
371 // ------------------------------------------------------------------------
372 virtual video::E_VERTEX_TYPE getVertexType() const
373 {
374 return video::EVT_SKINNED_MESH;
375 }
376 // ------------------------------------------------------------------------
377 virtual const core::vector3df& getPosition(u32 i) const
378 {
379 return m_vertices[i].m_position;
380 }
381 // ------------------------------------------------------------------------
382 virtual core::vector3df& getPosition(u32 i)
383 {
384 return m_vertices[i].m_position;
385 }
386 // ------------------------------------------------------------------------
387 virtual const core::vector3df& getNormal(u32 i) const
388 {
389 static core::vector3df unused;
390 return unused;
391 }
392 // ------------------------------------------------------------------------
393 virtual core::vector3df& getNormal(u32 i)
394 {
395 static core::vector3df unused;
396 return unused;
397 }
398 // ------------------------------------------------------------------------
399 virtual const core::vector2df& getTCoords(u32 i) const
400 {
401 static core::vector2df unused;
402 return unused;
403 }
404 // ------------------------------------------------------------------------
405 virtual core::vector2df& getTCoords(u32 i)
406 {
407 static core::vector2df unused;
408 return unused;
409 }
410 // ------------------------------------------------------------------------
411 virtual scene::E_PRIMITIVE_TYPE getPrimitiveType() const
412 {
413 return EPT_TRIANGLES;
414 }
415 // ------------------------------------------------------------------------
416 virtual void append(const void* const vertices, u32 numm_vertices,
417 const u16* const indices, u32 numm_indices) {}
418 // ------------------------------------------------------------------------
419 virtual void append(const IMeshBuffer* const other) {}
420 // ------------------------------------------------------------------------
421 virtual E_HARDWARE_MAPPING getHardwareMappingHint_Vertex() const
422 {
423 return EHM_NEVER;
424 }
425 // ------------------------------------------------------------------------
426 virtual E_HARDWARE_MAPPING getHardwareMappingHint_Index() const
427 {
428 return EHM_NEVER;
429 }
430 // ------------------------------------------------------------------------
431 virtual void setHardwareMappingHint(E_HARDWARE_MAPPING,
432 E_BUFFER_TYPE Buffer) {}
433 // ------------------------------------------------------------------------
434 virtual void setDirty(E_BUFFER_TYPE Buffer=EBT_VERTEX_AND_INDEX) {}
435 // ------------------------------------------------------------------------
436 virtual u32 getChangedID_Vertex() const { return 0; }
437 // ------------------------------------------------------------------------
438 virtual u32 getChangedID_Index() const { return 0; }
439
440};
441
442}
443
444#endif
Definition: material.hpp:48
Definition: sp_instanced_data.hpp:32
Definition: sp_mesh_buffer.hpp:48
Definition: sp_per_object_uniform.hpp:31
Definition: sp_shader.hpp:81
Declares the general types that are used by the network.