GlMesh.cpp
Go to the documentation of this file.
1 #include "GlMesh.hpp"
2 #include "../Defs.hpp"
3 #include "GlError.hpp"
4 #include <ivorium_config.hpp>
5 
6 namespace iv
7 {
8 
10  _vao( 0 ),
11  _position_buffer( 0 ),
12  _texcoord_buffer( 0 ),
13  _indices_buffer( 0 ),
14  _indices_cnt( 0 )
15 #if IV_ENABLE_TRANSFORM_FEEDBACK
16  , _tf_triangles_cnt( 0 )
17  , _tf_buffer( 0 )
18 #endif
19 {
20 }
21 
22 void GlMesh::Load_All( Context const * logger, GlMeshData const & data )
23 {
24  this->Load_Positions( logger, data.positions.data(), data.positions.size() );
25  this->Load_TexCoords( logger, data.texcoords.data(), data.texcoords.size() );
26  this->Load_Indices( logger, data.indices.data(), data.indices.size(), data.draw_mode );
27 }
28 
29 size_t GlMesh::indices_cnt() const
30 {
31  return this->_indices_cnt;
32 }
33 
34 void GlMesh::CreateMesh( Context const * logger )
35 {
36  if( this->_vao )
37  this->DestroyMesh( logger );
38 
39  glGenVertexArrays( 1, &this->_vao );
40 }
41 
42 void GlMesh::Load_Positions( Context const * logger, float const * data, size_t length )
43 {
44  if( !this->_vao )
45  this->CreateMesh( logger );
46 
47  if( !this->_position_buffer )
48  {
49  // create buffer
50  glGenBuffers( 1, &this->_position_buffer );
51 
52  // map it to VAO
53  glBindBuffer( GL_ARRAY_BUFFER, this->_position_buffer );
54  glBindVertexArray( this->_vao );
55  glVertexAttribPointer( AttributeLoc_Position, 3, GL_FLOAT, GL_FALSE, 0, nullptr );
56  glEnableVertexAttribArray( AttributeLoc_Position );
57  glBindVertexArray( 0 );
58  glBindBuffer( GL_ARRAY_BUFFER, 0 );
59  }
60 
61  // load data
62  glBindBuffer( GL_ARRAY_BUFFER, this->_position_buffer );
63  glBufferData( GL_ARRAY_BUFFER, sizeof( float ) * length, data, GL_STATIC_DRAW );
64  glBindBuffer( GL_ARRAY_BUFFER, 0 );
65 
66  GlError_Check( logger, SRC_INFO );
67 }
68 
69 void GlMesh::Load_TexCoords( Context const * logger, float const * data, size_t length )
70 {
71  if( !this->_vao )
72  this->CreateMesh( logger );
73 
74  if( !this->_texcoord_buffer )
75  {
76  // create buffer
77  glGenBuffers( 1, &this->_texcoord_buffer );
78 
79  // map it to VAO
80  glBindBuffer( GL_ARRAY_BUFFER, this->_texcoord_buffer );
81  glBindVertexArray( this->_vao );
82  glVertexAttribPointer( AttributeLoc_Texcoord, 2, GL_FLOAT, GL_FALSE, 0, nullptr );
83  glEnableVertexAttribArray( AttributeLoc_Texcoord );
84  glBindVertexArray( 0 );
85  glBindBuffer( GL_ARRAY_BUFFER, 0 );
86  }
87 
88  // load data
89  glBindBuffer( GL_ARRAY_BUFFER, this->_texcoord_buffer );
90  glBufferData( GL_ARRAY_BUFFER, sizeof( float ) * length, data, GL_STATIC_DRAW );
91  glBindBuffer( GL_ARRAY_BUFFER, 0 );
92 
93  GlError_Check( logger, SRC_INFO );
94 }
95 
96 void GlMesh::Load_Indices( Context const * logger, GLuint const * data, size_t length, GLenum draw_mode )
97 {
98  if( !this->_vao )
99  this->CreateMesh( logger );
100 
101  this->_draw_mode = draw_mode;
102 
103 #if IV_ENABLE_TRANSFORM_FEEDBACK
104  // count triangles
105  size_t triangles = 0;
106  if( draw_mode == GL_TRIANGLE_STRIP )
107  {
108  size_t active = 0;
109  for( size_t i = 0; i < length; i++ )
110  {
111  if( data[ i ] == PrimitiveRestart )
112  active = 0;
113  else
114  active += 1;
115 
116  if( active >= 3 )
117  triangles += 1;
118  }
119  }
120  else
121  {
122  logger->log( SRC_INFO, Defs::Log::Warning, "Unimplemented draw mode ", draw_mode, "for transform feedback. Transform feedback inactive." );
123  }
124  this->_tf_triangles_cnt = triangles;
125 
126 #endif
127 
128  //
129  if( !this->_indices_buffer )
130  {
131  // create buffer
132  glGenBuffers( 1, &this->_indices_buffer );
133 
134  // map it to VAO
135  glBindVertexArray( this->_vao );
136  glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, this->_indices_buffer ); //< NOTE - It seems that this does not bind element buffer to the VAO for some reason
137  glBindVertexArray( 0 );
138  glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
139  }
140 
141  glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, this->_indices_buffer );
142  glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof( GLuint ) * length, data, GL_STATIC_DRAW );
143  glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
144 
145  this->_indices_cnt = length;
146 
147  #if IV_ENABLE_TRANSFORM_FEEDBACK
148  if( this->_tf_buffer )
149  glDeleteBuffers( 1, &this->_tf_buffer );
150 
151  glGenBuffers( 1, &this->_tf_buffer );
152  glBindBuffer( GL_TRANSFORM_FEEDBACK_BUFFER, this->_tf_buffer );
153  glBufferData( GL_TRANSFORM_FEEDBACK_BUFFER, sizeof( float ) * this->_tf_triangles_cnt * 3 * 4, nullptr, GL_DYNAMIC_READ );
154  glBindBuffer( GL_TRANSFORM_FEEDBACK_BUFFER, 0 );
155 
156  this->_tf_data.resize( this->_tf_triangles_cnt * 3 * 4 );
157  #endif
158 
159  GlError_Check( logger, SRC_INFO );
160 }
161 
162 void GlMesh::DestroyMesh( Context const * logger )
163 {
164  if( this->_vao )
165  {
166  glDeleteVertexArrays( 1, &this->_vao );
167  this->_vao = 0;
168  }
169 
170  if( this->_position_buffer )
171  {
172  glDeleteBuffers( 1, &this->_position_buffer );
173  this->_position_buffer = 0;
174  }
175 
176  if( this->_texcoord_buffer )
177  {
178  glDeleteBuffers( 1, &this->_texcoord_buffer );
179  this->_texcoord_buffer = 0;
180  }
181 
182  if( this->_indices_buffer )
183  {
184  glDeleteBuffers( 1, &this->_indices_buffer );
185  this->_indices_buffer = 0;
186  }
187 
188  #if IV_ENABLE_TRANSFORM_FEEDBACK
189  if( this->_tf_buffer )
190  {
191  glDeleteBuffers( 1, &this->_tf_buffer );
192  this->_tf_buffer = 0;
193  }
194  #endif
195 
196  this->_indices_cnt = 0;
197  this->_draw_mode = GL_TRIANGLE_STRIP;
198 
199  GlError_Check( logger, SRC_INFO );
200 }
201 
202 void GlMesh::DropMesh( Context const * logger )
203 {
204  this->_vao = 0;
205  this->_position_buffer = 0;
206  this->_texcoord_buffer = 0;
207  this->_indices_buffer = 0;
208  this->_indices_cnt = 0;
209  #if IV_ENABLE_TRANSFORM_FEEDBACK
210  this->_tf_buffer = 0;
211  #endif
212  this->_draw_mode = GL_TRIANGLE_STRIP;
213 }
214 
215 void GlMesh::DrawElements( Context const * logger ) const
216 {
217  if( !this->_vao )
218  return;
219 
220  #if IV_ENABLE_TRANSFORM_FEEDBACK
221  bool tf_enabled = logger->log_enabled( Defs::Log::TransformFeedback );
222  if( tf_enabled )
223  {
224  glBindBufferBase( GL_TRANSFORM_FEEDBACK_BUFFER, 0, this->_tf_buffer );
225  glBeginTransformFeedback( GL_TRIANGLES );
226  }
227  #endif
228 
229  glBindVertexArray( this->_vao );
230  glDrawElements( this->_draw_mode, this->_indices_cnt, GL_UNSIGNED_INT, nullptr );
231  glBindVertexArray( 0 );
232 
233  #if IV_ENABLE_TRANSFORM_FEEDBACK
234  if( tf_enabled )
235  {
236  // end TF
237  glEndTransformFeedback();
238 
239  // bind
240  glBindBufferBase( GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0 );
241  glBindBuffer( GL_TRANSFORM_FEEDBACK_BUFFER, this->_tf_buffer );
242 
243  // read buffer
244  size_t tf_buffer_length = sizeof( float ) * this->_tf_triangles_cnt * 3 * 4;
245  #if IV_GLPLATFORM_GLFW
246  {
247  glGetBufferSubData( GL_TRANSFORM_FEEDBACK_BUFFER, 0, tf_buffer_length, (void*)this->_tf_data.data() );
248  }
249  #elif IV_GLPLATFORM_GLFM
250  {
251  void * buff = glMapBufferRange( GL_TRANSFORM_FEEDBACK_BUFFER, 0, tf_buffer_length, GL_MAP_READ_BIT );
252  if( buff )
253  memcpy( (void*)this->_tf_data.data(), buff, tf_buffer_length );
254  else
255  logger->log_frame( Defs::Log::TransformFeedback, "Failed to retrieve transform feedback (glMapBufferRange returns nullptr)." );
256 
257  glUnmapBuffer( GL_TRANSFORM_FEEDBACK_BUFFER );
258  GlError_Check( logger, SRC_INFO );
259  }
260  #else
261  #error "Unknown OpenGL platform."
262  #endif
263 
264  // unbind
265  glBindBuffer( GL_TRANSFORM_FEEDBACK_BUFFER, 0 );
266 
267  for( size_t i = 0; i < this->_tf_triangles_cnt; i++ )
268  {
270  "Triangle", Context::Endl(),
271  Context::Begin(),
272  " (", this->_tf_data[ i*12 + 0 ], ", ", this->_tf_data[ i*12 + 1 ], ", ", this->_tf_data[ i*12 + 2 ], ", ", this->_tf_data[ i*12 + 3 ], ")", Context::Endl(),
273  " (", this->_tf_data[ i*12 + 4 ], ", ", this->_tf_data[ i*12 + 5 ], ", ", this->_tf_data[ i*12 + 6 ], ", ", this->_tf_data[ i*12 + 7 ], ")", Context::Endl(),
274  " (", this->_tf_data[ i*12 + 8 ], ", ", this->_tf_data[ i*12 + 9 ], ", ", this->_tf_data[ i*12 + 10 ], ", ", this->_tf_data[ i*12 + 11 ], ")",
275  Context::End()
276  );
277  }
278  }
279  #endif
280 }
281 
282 }