SuperTuxKart
sp_dynamic_draw_call.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_DYNAMIC_DRAW_CALL_HPP
19 #define HEADER_SP_DYNAMIC_DRAW_CALL_HPP
20 
21 #include "graphics/sp/sp_mesh_buffer.hpp"
22 
23 #include <IMeshBuffer.h>
24 #include <ISceneNode.h>
25 
26 #include <array>
27 #include <cassert>
28 #include <string>
29 #include <tuple>
30 #include <unordered_map>
31 #include <vector>
32 
33 using namespace irr;
34 
35 class Material;
36 
37 namespace SP
38 {
39 class SPShader;
40 
42 {
43 private:
44  core::matrix4 m_trans;
45 
46  scene::ISceneNode* m_parent = NULL;
47 
48  core::vector2df m_texture_trans;
49 
50  scene::E_PRIMITIVE_TYPE m_primitive_type;
51 
52  unsigned m_gl_vbo_size = 4;
53 
54  int m_update_offset = 0;
55 
56  bool m_visible = true;
57 
58  bool m_update_trans = false;
59 
60  bool m_removing = false;
61 
62  // ------------------------------------------------------------------------
63  bool initTextureDyDc();
64 
65 public:
66  SPDynamicDrawCall(scene::E_PRIMITIVE_TYPE pt,
67  std::shared_ptr<SPShader> shader, Material* m);
68  // ------------------------------------------------------------------------
69  ~SPDynamicDrawCall() {}
70  // ------------------------------------------------------------------------
71  virtual void draw(DrawCallType dct = DCT_NORMAL,
72  int material_id = -1) const
73  {
74 #ifndef SERVER_ONLY
75  glBindVertexArray(m_vao[0]);
76  glDrawArraysInstanced(
77  m_primitive_type == EPT_TRIANGLES ? GL_TRIANGLES :
78  m_primitive_type == EPT_TRIANGLE_STRIP ? GL_TRIANGLE_STRIP :
79  GL_TRIANGLE_FAN, 0, getVertexCount(), 1);
80 #endif
81  }
82  // ------------------------------------------------------------------------
83  virtual void uploadInstanceData()
84  {
85 #ifndef SERVER_ONLY
86  if (m_texture_trans.X != 0.0f || m_texture_trans.Y != 0.0f ||
87  m_update_trans || m_parent != NULL)
88  {
89  m_update_trans = false;
90  SPInstancedData id = SPInstancedData(getAbsoluteTransformation(),
91  m_texture_trans.X, m_texture_trans.Y, 0.0f, 0);
92  glBindBuffer(GL_ARRAY_BUFFER, m_ibo);
93  glBufferSubData(GL_ARRAY_BUFFER, 0, 44, id.getData());
94  glBindBuffer(GL_ARRAY_BUFFER, 0);
95  }
96  if (m_update_offset >= 0 && !m_vertices.empty())
97  {
98  glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
99  unsigned new_size = m_gl_vbo_size;
100  while (m_vertices.size() > new_size)
101  {
102  // Power of 2 allocation strategy, like std::vector in gcc
103  new_size <<= 1;
104  }
105  if (new_size != m_gl_vbo_size)
106  {
107  m_update_offset = 0;
108  m_gl_vbo_size = new_size;
109  m_vertices.reserve(m_gl_vbo_size);
110  glBufferData(GL_ARRAY_BUFFER, m_gl_vbo_size * 48,
111  m_vertices.data(), GL_DYNAMIC_DRAW);
112  }
113  else
114  {
115  const int length =
116  ((int)m_vertices.size() - m_update_offset) * 48;
117  assert(length > 0);
118  glBufferSubData(GL_ARRAY_BUFFER, m_update_offset * 48, length,
119  m_vertices.data() + m_update_offset);
120  }
121  glBindBuffer(GL_ARRAY_BUFFER, 0);
122  m_update_offset = -1;
123  }
124 #endif
125  }
126  // ------------------------------------------------------------------------
127  virtual void uploadGLMesh() {}
128  // ------------------------------------------------------------------------
129  virtual void enableTextureMatrix(unsigned mat_id) {}
130  // ------------------------------------------------------------------------
131  std::vector<video::S3DVertexSkinnedMesh>& getVerticesVector()
132  { return m_vertices; }
133  // ------------------------------------------------------------------------
134  core::vector2df& getTextureTrans()
135  {
136  m_update_trans = true;
137  return m_texture_trans;
138  }
139  // ------------------------------------------------------------------------
140  void setUpdateOffset(int offset)
141  {
142  // Avoid skipping of vertex buffer update if this function is called
143  // more than once per frame
144  if (m_update_offset != -1 && offset > m_update_offset)
145  return;
146  m_update_offset = offset;
147  }
148  // ------------------------------------------------------------------------
149  bool isVisible() const { return m_visible; }
150  // ------------------------------------------------------------------------
151  void setVisible(bool val) { m_visible = val; }
152  // ------------------------------------------------------------------------
153  core::matrix4 getAbsoluteTransformation() const
154  {
155  core::matrix4 trans = m_trans;
156  if (m_parent != NULL)
157  {
158  trans = m_parent->getAbsoluteTransformation() * trans;
159  }
160  return trans;
161  }
162  // ------------------------------------------------------------------------
163  void removeFromSP() { m_removing = true; }
164  // ------------------------------------------------------------------------
165  bool isRemoving() const { return m_removing; }
166  // ------------------------------------------------------------------------
167  bool notReadyFromDrawing() const { return m_vertices.size() < 3; }
168  // ------------------------------------------------------------------------
169  void setTransformation(const core::matrix4& mat)
170  {
171  m_trans = mat;
172  m_update_trans = true;
173  }
174  // ------------------------------------------------------------------------
175  void setPosition(const core::vector3df pos)
176  {
177  m_trans.setTranslation(pos);
178  m_update_trans = true;
179  }
180  // ------------------------------------------------------------------------
181  void setRotationRadians(const core::vector3df rot)
182  {
183  m_trans.setRotationRadians(rot);
184  m_update_trans = true;
185  }
186  // ------------------------------------------------------------------------
187  void setRotationDegrees(const core::vector3df rot)
188  {
189  m_trans.setRotationDegrees(rot);
190  m_update_trans = true;
191  }
192  // ------------------------------------------------------------------------
193  void setScale(const core::vector3df scale)
194  {
195  m_trans.setScale(scale);
196  m_update_trans = true;
197  }
198  // ------------------------------------------------------------------------
199  void setParent(scene::ISceneNode* parent) { m_parent = parent; }
200 
201 };
202 
203 }
204 
205 #endif
Definition: material.hpp:48
Definition: sp_dynamic_draw_call.hpp:42
Definition: sp_instanced_data.hpp:32
Definition: sp_mesh_buffer.hpp:48