Developer Documentation

SplatCloudNode.cc
1 /*===========================================================================*\
2 * *
3 * OpenFlipper *
4 * Copyright (c) 2001-2015, RWTH-Aachen University *
5 * Department of Computer Graphics and Multimedia *
6 * All rights reserved. *
7 * www.openflipper.org *
8 * *
9 *---------------------------------------------------------------------------*
10 * This file is part of OpenFlipper. *
11 *---------------------------------------------------------------------------*
12 * *
13 * Redistribution and use in source and binary forms, with or without *
14 * modification, are permitted provided that the following conditions *
15 * are met: *
16 * *
17 * 1. Redistributions of source code must retain the above copyright notice, *
18 * this list of conditions and the following disclaimer. *
19 * *
20 * 2. Redistributions in binary form must reproduce the above copyright *
21 * notice, this list of conditions and the following disclaimer in the *
22 * documentation and/or other materials provided with the distribution. *
23 * *
24 * 3. Neither the name of the copyright holder nor the names of its *
25 * contributors may be used to endorse or promote products derived from *
26 * this software without specific prior written permission. *
27 * *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 \*===========================================================================*/
41
42
43
44 //================================================================
45 //
46 // CLASS SplatCloudNode - IMPLEMENTATION
47 //
48 //================================================================
49
50
51 //== INCLUDES ====================================================
52
53 #include <ACG/GL/acg_glew.hh>
54 #include <ACG/GL/IRenderer.hh>
55
56 #include "SplatCloudNode.hh"
57
58
59 //== DEFINES =====================================================
60
61
62 //#define REPORT_VBO_UPDATES
63
64
65 //== NAMESPACES ==================================================
66
67
68 namespace ACG {
69 namespace SceneGraph {
70
71 //== STATIC MEMBER VARIABLES =====================================
72
73
74 const SplatCloudNode::Position SplatCloudNode::DEFAULT_POSITION (0,0,0);
75 const SplatCloudNode::Index SplatCloudNode::DEFAULT_INDEX ( -1);
76 const SplatCloudNode::Viewlist SplatCloudNode::DEFAULT_VIEWLIST ( 0.0);
77 const SplatCloudNode::Selection SplatCloudNode::DEFAULT_SELECTION(false);
78
79
80 //== IMPLEMENTATION ==============================================
81
82
83 SplatCloudNode::SplatCloudNode( const SplatCloud &_splatCloud, BaseNode *_parent, std::string _name ) :
84 BaseNode ( _parent, _name ),
85 splatCloud_ ( _splatCloud ),
86 positionsModified_ ( false ),
87 colorsModified_ ( false ),
88 normalsModified_ ( false ),
89 pointsizesModified_ ( false ),
90 selectionsModified_ ( false ),
91 pickColorsModified_ ( false ),
92 defaultColor_ ( Color (0,0,0) ),
93 defaultNormal_ ( Normal (0,0,0) ),
94 defaultPointsize_ ( Pointsize( 0.0) ),
95 splatsDrawMode_ ( DrawModes::addDrawMode( "Splats" ) ),
96 dotsDrawMode_ ( DrawModes::addDrawMode( "Dots" ) ),
97 pointsDrawMode_ ( DrawModes::addDrawMode( "Points" ) ),
98 pickingBaseIndex_ ( 0 ),
99 pickDrawMode_ ( DrawModes::NONE ), // TODO: hack, see enterPick()
100 vboGlId_ ( 0 ),
101 vboNumSplats_ ( 0 ),
102 vboData_ ( 0 ),
103 vboStride_ ( 0 ),
104 vboPositionsOffset_ ( -1 ),
105 vboColorsOffset_ ( -1 ),
106 vboNormalsOffset_ ( -1 ),
107 vboPointsizesOffset_( -1 ),
108 vboSelectionsOffset_( -1 ),
109 vboPickColorsOffset_( -1 ),
110 pointsizeScale_ ( 1.0f ),
111 backfaceCulling_ ( false ),
112 geometryShaderQuads_( false )
113 {
114 // create a new VBO (will be invalid and rebuilt the next time drawn (or picked))
115 createVBO();
116 }
117
118
119 //----------------------------------------------------------------
120
121
122 SplatCloudNode::~SplatCloudNode()
123 {
124 destroyVBO();
125 }
126
127
128 //----------------------------------------------------------------
129
130
131 void SplatCloudNode::boundingBox( ACG::Vec3d &_bbMin, ACG::Vec3d &_bbMax )
132 {
133 ACG::Vec3f bbMin( FLT_MAX, FLT_MAX, FLT_MAX );
134 ACG::Vec3f bbMax(-FLT_MAX,-FLT_MAX,-FLT_MAX );
135
136 if( splatCloud_.hasPositions() )
137 {
138 unsigned int i, num = splatCloud_.numSplats();
139 for( i=0; i<num; ++i )
140 {
141 const Position &p = splatCloud_.positions( i );
142
143 ACG::Vec3f acgp( p[0], p[1], p[2] );
144
145 bbMin.minimize( acgp );
146 bbMax.maximize( acgp );
147 }
148 }
149
150 _bbMin.minimize( ACG::Vec3d( bbMin ) );
151 _bbMax.maximize( ACG::Vec3d( bbMax ) );
152 }
153
154
155 //----------------------------------------------------------------
156
157
158 void SplatCloudNode::draw( GLState &_state, const DrawModes::DrawMode &_drawMode )
159 {
160
161 static const int RENDERMODE_DOTS = 1;
162 static const int RENDERMODE_SPLATS = 2;
163
164 // check if drawmode is valid
165 int rendermode;
166 if( _drawMode.containsAtomicDrawMode( splatsDrawMode_ ) )
167 rendermode = RENDERMODE_SPLATS;
168 else if( _drawMode.containsAtomicDrawMode( dotsDrawMode_ ) )
169 rendermode = RENDERMODE_DOTS;
170 else if( _drawMode.containsAtomicDrawMode( pointsDrawMode_ ) ) {
171 static const int RENDERMODE_POINTS = 0;
172 rendermode = RENDERMODE_POINTS;
173 } else
174 return;
175
176 // set desired depth function
177 ACG::GLState::depthFunc( _state.depthFunc() );
178
179 // if VBO is invalid or was (partially) modified, then rebuild
180 if( (vboData_ == 0) || vboModified() )
181 rebuildVBO( _state );
182
183 // if VBO is valid...
184 if( vboData_ != 0 )
185 {
186 // activate VBO
187 ACG::GLState::bindBufferARB( GL_ARRAY_BUFFER_ARB, vboGlId_ );
188
189 // enable arrays:
190 // --------------
191
192 // positions
193 if( vboPositionsOffset_ != -1 )
194 {
195 ACG::GLState::enableClientState( GL_VERTEX_ARRAY );
196 ACG::GLState::vertexPointer( 3, GL_FLOAT, static_cast<GLsizei>(vboStride_), (unsigned char *) 0 + vboPositionsOffset_ );
197 }
198 else
199 {
200 ACG::GLState::disableClientState( GL_VERTEX_ARRAY );
201 }
202
203 // colors
204 if( vboColorsOffset_ != -1 )
205 {
206 ACG::GLState::enableClientState( GL_SECONDARY_COLOR_ARRAY );
207 glSecondaryColorPointer( 3, GL_UNSIGNED_BYTE, static_cast<GLsizei>(vboStride_), (unsigned char *) 0 + vboColorsOffset_ ); // TODO: use ACG::GLState::secondaryColorPointer() when implemented
208 }
209 else
210 {
211 ACG::GLState::disableClientState( GL_SECONDARY_COLOR_ARRAY );
212 glSecondaryColor3ub( defaultColor_[0], defaultColor_[1], defaultColor_[2] );
213 }
214
215 // normals
216 if( vboNormalsOffset_ != -1 )
217 {
218 ACG::GLState::enableClientState( GL_NORMAL_ARRAY );
219 ACG::GLState::normalPointer( GL_FLOAT, static_cast<GLsizei>(vboStride_), (unsigned char *) 0 + vboNormalsOffset_ );
220 }
221 else
222 {
223 ACG::GLState::disableClientState( GL_NORMAL_ARRAY );
224 glNormal3f( defaultNormal_[0], defaultNormal_[1], defaultNormal_[2] );
225 }
226
227 // pointsizes
228 if( vboPointsizesOffset_ != -1 )
229 {
230 glClientActiveTexture( GL_TEXTURE0 ); // TODO: use ACG::GLState::clientActiveTexture() when implemented
231 ACG::GLState::enableClientState( GL_TEXTURE_COORD_ARRAY );
232 ACG::GLState::texcoordPointer( 1, GL_FLOAT, static_cast<GLsizei>(vboStride_), (unsigned char *) 0 + vboPointsizesOffset_ );
233 }
234 else
235 {
236 glClientActiveTexture( GL_TEXTURE0 ); // TODO: use ACG::GLState::clientActiveTexture() when implemented
237 ACG::GLState::disableClientState( GL_TEXTURE_COORD_ARRAY );
238 glMultiTexCoord1f( GL_TEXTURE0, defaultPointsize_ );
239 }
240
241 // selections
242 if( vboSelectionsOffset_ != -1 )
243 {
244 glClientActiveTexture( GL_TEXTURE1 ); // TODO: use ACG::GLState::clientActiveTexture() when implemented
245 ACG::GLState::enableClientState( GL_TEXTURE_COORD_ARRAY );
246 ACG::GLState::texcoordPointer( 1, GL_FLOAT, static_cast<GLsizei>(vboStride_), (unsigned char *) 0 + vboSelectionsOffset_ );
247 }
248 else
249 {
250 glClientActiveTexture( GL_TEXTURE1 ); // TODO: use ACG::GLState::clientActiveTexture() when implemented
251 ACG::GLState::disableClientState( GL_TEXTURE_COORD_ARRAY );
252 glMultiTexCoord1f( GL_TEXTURE1, 0.0f );
253 }
254
255 // pick colors
256 if( vboPickColorsOffset_ != -1 )
257 {
258 ACG::GLState::enableClientState( GL_COLOR_ARRAY );
259 ACG::GLState::colorPointer( 4, GL_UNSIGNED_BYTE, static_cast<GLsizei>(vboStride_), (unsigned char *) 0 + vboPickColorsOffset_ );
260 }
261 else
262 {
263 ACG::GLState::disableClientState( GL_COLOR_ARRAY );
264 glColor4ub( 255, 255, 255, 255 );
265 }
266
267 // render:
268 // -------
269
270 // enable "pointsize by program" depending on current rendermode
271 if( rendermode == RENDERMODE_SPLATS || rendermode == RENDERMODE_DOTS )
272 ACG::GLState::enable( GL_VERTEX_PROGRAM_POINT_SIZE );
273 else
274 ACG::GLState::disable( GL_VERTEX_PROGRAM_POINT_SIZE );
275
276 // draw as GLpoints
277 glDrawArrays( GL_POINTS, 0, vboNumSplats_ );
278
279 // disable arrays:
280 // ---------------
281
282 // positions
283 ACG::GLState::disableClientState( GL_VERTEX_ARRAY );
284
285 // colors
286 ACG::GLState::disableClientState( GL_SECONDARY_COLOR_ARRAY );
287
288 // normals
289 ACG::GLState::disableClientState( GL_NORMAL_ARRAY );
290
291 // pointsizes
292 glClientActiveTexture( GL_TEXTURE0 ); // TODO: use ACG::GLState::clientActiveTexture() when implemented
293 ACG::GLState::disableClientState( GL_TEXTURE_COORD_ARRAY );
294
295 // selections
296 glClientActiveTexture( GL_TEXTURE1 ); // TODO: use ACG::GLState::clientActiveTexture() when implemented
297 ACG::GLState::disableClientState( GL_TEXTURE_COORD_ARRAY );
298
299 // pick colors
300 ACG::GLState::disableClientState( GL_COLOR_ARRAY );
301
302 // reset states:
303 // -------------
304
305 // disable "pointsize by program"
306 ACG::GLState::disable( GL_VERTEX_PROGRAM_POINT_SIZE );
307
308 // make defaults current again
309 glClientActiveTexture( GL_TEXTURE0 ); // TODO: use ACG::GLState::clientActiveTexture() when implemented
310 glColor4f ( 1.0f, 1.0f, 1.0f, 1.0f );
311 glSecondaryColor3f( 1.0f, 1.0f, 1.0f );
312
313 // deactivate VBO
314 ACG::GLState::bindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
315 }
316 }
317
318 //----------------------------------------------------------------
319
320 void SplatCloudNode::getRenderObjects( IRenderer* _renderer, GLState& _state, const DrawModes::DrawMode& _drawMode, const Material* _mat )
321 {
322 static const int RENDERMODE_POINTS = 0;
323 static const int RENDERMODE_DOTS = 1;
324 static const int RENDERMODE_SPLATS = 2;
325
326 // check if drawmode is valid
327 int rendermode;
328 if (_drawMode.containsAtomicDrawMode(splatsDrawMode_))
329 rendermode = RENDERMODE_SPLATS;
330 else if (_drawMode.containsAtomicDrawMode(dotsDrawMode_))
331 rendermode = RENDERMODE_DOTS;
332 else if (_drawMode.containsAtomicDrawMode(pointsDrawMode_)) {
333 rendermode = RENDERMODE_POINTS;
334 }
335 else
336 return;
337
338 ACG::RenderObject obj;
339
340 obj.initFromState(&_state);
341 obj.setMaterial(_mat);
342
343 obj.depthTest = true;
344
345 // backface culling is done manually in shader
346 obj.culling = false;
347
348 // if VBO is invalid or was (partially) modified, then rebuild
349 if ((vboData_ == 0) || vboModified())
350 rebuildVBO(_state);
351
352 // if VBO is valid...
353 if (vboData_ != 0)
354 {
355 // activate VBO
356 obj.vertexBuffer = vboGlId_;
357
358
359 // enable arrays:
360 // --------------
361 vboDecl_.clear();
362
363 // positions
364 if (vboPositionsOffset_ != -1)
365 vboDecl_.addElement(GL_FLOAT, 3, ACG::VERTEX_USAGE_POSITION, size_t(vboPositionsOffset_));
366
367 // colors
368 if (vboColorsOffset_ != -1)
369 vboDecl_.addElement(GL_UNSIGNED_BYTE, 3, ACG::VERTEX_USAGE_COLOR, size_t(vboColorsOffset_));
370 else
371 {
372 obj.emissive = ACG::Vec3f(defaultColor_[0], defaultColor_[1], defaultColor_[2]);
373 obj.emissive /= 255.0f;
374 }
375
376 // normals
377 if (vboNormalsOffset_ != -1)
378 vboDecl_.addElement(GL_FLOAT, 3, ACG::VERTEX_USAGE_NORMAL, size_t(vboNormalsOffset_));
379 else
380 {
381 // todo
382 // defaultNormal_;
383 }
384
385 // pointsizes
386 if (vboPointsizesOffset_ != -1)
387 vboDecl_.addElement(GL_FLOAT, 1, ACG::VERTEX_USAGE_TEXCOORD, size_t(vboPointsizesOffset_));
388 else
389 {
390 // todo
391 // glMultiTexCoord1f(GL_TEXTURE0, defaultPointsize_);
392 }
393
394 // selections
395 if (vboSelectionsOffset_ != -1)
396 vboDecl_.addElement(GL_FLOAT, 1, ACG::VERTEX_USAGE_SHADER_INPUT, size_t(vboSelectionsOffset_), "inSplatSelection");
397 else
398 {
399 // todo
400 // glMultiTexCoord1f(GL_TEXTURE1, 0.0f);
401 }
402
403 // pick colors
404 if (vboPickColorsOffset_ != -1)
405 vboDecl_.addElement(GL_UNSIGNED_BYTE, 4, ACG::VERTEX_USAGE_SHADER_INPUT, size_t(vboPickColorsOffset_), "inSplatPickColor");
406 else
407 {
408 // todo
409 // glColor4ub(255, 255, 255, 255);
410 }
411
412 vboDecl_.setVertexStride(vboStride_);
413
414 obj.vertexDecl = &vboDecl_;
415
416 // render:
417 // -------
418
419 // setup shader
420 obj.shaderDesc.shadeMode = SG_SHADE_UNLIT;
421
422
423
424 obj.programPointSize = false;
425
426 // test gl_PointSize performance
427 if (rendermode == RENDERMODE_DOTS)
428 {
429
430 }
431
432
433 switch (rendermode)
434 {
435 case RENDERMODE_SPLATS:
436 {
437 if (geometryShaderQuads_)
438 {
439 obj.shaderDesc.vertexTemplateFile = "SplatCloud_ShaderGen/splats_quad_vs.glsl";
440 obj.shaderDesc.geometryTemplateFile = "SplatCloud_ShaderGen/splats_quad_gs.glsl";
441 obj.shaderDesc.fragmentTemplateFile = "SplatCloud_ShaderGen/splats_quad_fs.glsl";
442 obj.programPointSize = false;
443 }
444 else
445 {
446 obj.shaderDesc.vertexTemplateFile = "SplatCloud_ShaderGen/splats_psize_vs.glsl";
447 obj.shaderDesc.fragmentTemplateFile = "SplatCloud_ShaderGen/splats_psize_fs.glsl";
448 obj.programPointSize = true;
449 }
450 } break;
451
452 case RENDERMODE_DOTS:
453 {
454 if (geometryShaderQuads_)
455 {
456 obj.shaderDesc.vertexTemplateFile = "SplatCloud_ShaderGen/dots_quad_vs.glsl";
457 obj.shaderDesc.geometryTemplateFile = "SplatCloud_ShaderGen/splats_quad_gs.glsl";
458 obj.shaderDesc.fragmentTemplateFile = "SplatCloud_ShaderGen/splats_quad_fs.glsl";
459 obj.programPointSize = false;
460 }
461 else
462 {
463 obj.shaderDesc.vertexTemplateFile = "SplatCloud_ShaderGen/dots_psize_vs.glsl";
464 obj.programPointSize = true;
465 }
466 } break;
467
468 case RENDERMODE_POINTS:
469 {
470 obj.shaderDesc.vertexTemplateFile = "SplatCloud_ShaderGen/points_vs.glsl";
471 obj.programPointSize = false;
472 } break;
473
474 default: break;
475 }
476
477 // setup uniforms
478 /*
479 uniform float pointsizeScale = 1.0;
480 uniform bool backfaceCulling = false;
481 uniform float modelviewScale;
482 uniform float viewportScaleFov_y;
483
484 uniform mat4 g_mPInv;
485
486 uniform vec4 invViewportScale;
487 uniform vec4 invViewportTransp;
488 uniform float viewportScale_z;
489 uniform float viewportTransp_z;
490 */
491
492 // get viewport
493 int left, bottom, width, height;
494 _state.get_viewport(left, bottom, width, height);
495
496 float x = (float)left;
497 float y = (float)bottom;
498 float w = (float)width;
499 float h = (float)height;
500
501 // get depthrange
502 // TODO: use glstate.get_depth_range when implemented
503 GLfloat depthRange[2];
504 glGetFloatv(GL_DEPTH_RANGE, depthRange);
505 float z = (float)depthRange[0];
506 float d = (float)depthRange[1] - z;
507
508 // check if we are safe
509 if (w <= 0.0f || h <= 0.0f || d <= 0.0f)
510 return;
511
512 // calculate window-coordinates to normalized-device-coordinates scale
513 ACG::Vec4f invVPs;
514 invVPs[0] = 2.0f / w;
515 invVPs[1] = 2.0f / h;
516 invVPs[2] = 2.0f / d;
517 invVPs[3] = 0.0f;
518
519 // calculate window-coordinates to normalized-device-coordinates transpose
520 ACG::Vec4f invVPt;
521 invVPt[0] = -(x * invVPs[0] + 1.0f);
522 invVPt[1] = -(y * invVPs[1] + 1.0f);
523 invVPt[2] = -(z * invVPs[2] + 1.0f);
524 invVPt[3] = 1.0f;
525
526 // calculate normalized-device-coordinates to window-coordinates scale and transpose
527 GLfloat VPs_z = 0.5f * d;
528 GLfloat VPt_z = z + VPs_z;
529
530 // calculate scaling factor of modelview matrix
531 static const double RCP_3 = 1.0 / 3.0;
532 const ACG::GLMatrixd &mv = _state.modelview();
533 double detMV = mv(0, 0) * (mv(1, 1)*mv(2, 2) - mv(1, 2)*mv(2, 1))
534 + mv(0, 1) * (mv(1, 2)*mv(2, 0) - mv(1, 0)*mv(2, 2))
535 + mv(0, 2) * (mv(1, 0)*mv(2, 1) - mv(1, 1)*mv(2, 0));
536 GLfloat MVs = (GLfloat)pow(fabs(detMV), RCP_3);
537
538 // calculate scale for pointsizes in eye-coordinates according to fovy and transformation to window-coordinates
539 GLfloat VPsFov_y = _state.projection()(1, 1) * (0.5f * h);
540
541 ACG::GLMatrixf projInv = _state.inverse_projection();
542
543 obj.setUniform("invViewportScale", invVPs);
544 obj.setUniform("invViewportTransp", invVPt);
545 obj.setUniform("viewportScale_z", VPs_z);
546 obj.setUniform("viewportTransp_z", VPt_z);
547 obj.setUniform("modelviewScale", MVs);
548 obj.setUniform("viewportScaleFov_y", VPsFov_y);
549 obj.setUniform("invProjection", projInv);
550 obj.setUniform("pointsizeScale", pointsizeScale_);
551 obj.setUniform("backfaceCulling", backfaceCulling_);
552 obj.setUniform("defaultPointsize", defaultPointsize_);
553 obj.setUniform("defaultNormal", defaultNormal_);
554
555 if (vboColorsOffset_ != -1)
556 obj.shaderDesc.vertexColors = true;
557
558 // draw as GLpoints
559 obj.glDrawArrays(GL_POINTS, 0, vboNumSplats_);
560
561 _renderer->addRenderObject(&obj);
562 }
563 }
564
565 //----------------------------------------------------------------
566
567
568 void SplatCloudNode::pick( GLState &_state, PickTarget _target )
569 {
570 // if pick target is valid...
571 if( _target == PICK_ANYTHING || _target == PICK_VERTEX )
572 {
573 // set number of pick colors used (each splats gets a unique pick color)
574 if( !_state.pick_set_maximum( splatCloud_.numSplats() ) ) // number of splats could have changed, so use new number of splats (*not* the one in VBO memory!)
575 {
576 std::cerr << "SplatCloudNode::pick() : Color range too small, picking failed." << std::endl;
577 return;
578 }
579
580 // if in color picking mode...
581 if( _state.color_picking() )
582 {
583 // if picking base index has changed, rebuild pick colors block in VBO so new pick colors will be used
584 if( pickingBaseIndex_ != _state.pick_current_index() )
585 {
586 pickColorsModified_ = true;
587 }
588
589 // TODO: hack, see enterPick()
590 draw( _state, pickDrawMode_ );
591 }
592 }
593 }
594
595
596 //----------------------------------------------------------------
597
598
599 void SplatCloudNode::createVBO()
600 {
601 // create new VBO (if *not* already existing)
602 if( vboGlId_ == 0 )
603 {
604 glGenBuffers( 1, &vboGlId_ );
605 vboNumSplats_ = 0;
606 vboData_ = 0;
607
608 modifiedAll(); // (re-)build all data block in VBO memory the first time
609 }
610 }
611
612
613 //----------------------------------------------------------------
614
615
616 void SplatCloudNode::destroyVBO()
617 {
618 // delete VBO (if existing)
619 if( vboGlId_ != 0 )
620 {
621 glDeleteBuffers( 1, &vboGlId_ );
622 vboGlId_ = 0;
623 vboNumSplats_ = 0;
624 vboData_ = 0;
625 }
626 }
627
628
629 //----------------------------------------------------------------
630
631
632 void SplatCloudNode::rebuildVBO( GLState &_state )
633 {
634 // if something went wrong in the initialization, make VBO invalid and abort
635 if( vboGlId_ == 0 )
636 {
637 vboData_ = 0;
638 return;
639 }
640
641 // activate VBO
642 ACG::GLState::bindBufferARB( GL_ARRAY_BUFFER_ARB, vboGlId_ );
643
644 // calculate size of data and offsets
645 unsigned int numSplats = splatCloud_.numSplats();
646 unsigned int stride = 0;
647
648 int positionsOffset = -1;
649 int colorsOffset = -1;
650 int normalsOffset = -1;
651 int pointsizesOffset = -1;
652 int selectionsOffset = -1;
653 int pickColorsOffset = -1;
654
655 if( splatCloud_.hasPositions() ) { positionsOffset = stride; stride += 12; }
656 if( splatCloud_.hasColors() ) { colorsOffset = stride; stride += 3; }
657 if( splatCloud_.hasNormals() ) { normalsOffset = stride; stride += 12; }
658 if( splatCloud_.hasPointsizes() ) { pointsizesOffset = stride; stride += 4; }
659 if( splatCloud_.hasSelections() ) { selectionsOffset = stride; stride += 4; }
660 /* has pick colors is true */ { pickColorsOffset = stride; stride += 4; }
661
662 // tell GL that we are seldomly updating the VBO but are often drawing it
663 glBufferData( GL_ARRAY_BUFFER_ARB, static_cast<GLsizei>(stride * numSplats), 0, GL_STATIC_DRAW_ARB );
664
665 // get pointer to VBO memory
666 unsigned char *data = (unsigned char *) glMapBuffer( GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB );
667
668 // check if something went wrong during VBO mapping
669 if( data == 0 )
670 {
671 std::cout << "SplatCloudNode::rebuildVBO() : glMapBuffer() failed." << std::endl;
672 vboData_ = 0;
673 }
674 else
675 {
676 // if VBO memory block was moved or the internal block structure has to be changed, rebuild entire VBO
677 if( (vboData_ != data) || vboStructureModified() )
678 {
679 vboNumSplats_ = numSplats;
680 vboData_ = data;
681 vboStride_ = stride;
682
683 vboPositionsOffset_ = positionsOffset;
684 vboColorsOffset_ = colorsOffset;
685 vboNormalsOffset_ = normalsOffset;
686 vboPointsizesOffset_ = pointsizesOffset;
687 vboSelectionsOffset_ = selectionsOffset;
688 vboPickColorsOffset_ = pickColorsOffset;
689
690 // mark all data blocks to rebuild them lateron
691 modifiedAll();
692 }
693
694 // if in color picking mode...
695 if( _state.color_picking() )
696 {
697 // store picking base index
698 pickingBaseIndex_ = static_cast<unsigned int>(_state.pick_current_index());
699 }
700
701 // rebuild data blocks if needed
702 if( positionsModified_ ) rebuildVBOPositions();
703 if( colorsModified_ ) rebuildVBOColors();
704 if( normalsModified_ ) rebuildVBONormals();
705 if( pointsizesModified_ ) rebuildVBOPointsizes();
706 if( selectionsModified_ ) rebuildVBOSelections();
707 if( pickColorsModified_ ) rebuildVBOPickColors( _state );
708
709 # ifdef REPORT_VBO_UPDATES
710 std::cout << std::endl;
711 # endif
712
713 // every block in VBO memory has been updated
714 positionsModified_ = false;
715 colorsModified_ = false;
716 normalsModified_ = false;
717 pointsizesModified_ = false;
718 selectionsModified_ = false;
719 pickColorsModified_ = false;
720
721 // release pointer to VBO memory. if something went wrong, make VBO invalid and abort
722 if( !glUnmapBuffer( GL_ARRAY_BUFFER_ARB ) )
723 {
724 std::cout << "SplatCloudNode::rebuildVBO() : glUnmapBuffer() failed." << std::endl;
725 vboData_ = 0;
726 }
727 }
728
729 // deactivate VBO
730 ACG::GLState::bindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
731 }
732
733
734 //----------------------------------------------------------------
735
736
737 static void addFloatToBuffer( float _value, unsigned char *&_buffer )
738 {
739 // get pointer
740 unsigned char *v = (unsigned char *) &_value;
741
742 // copy over 4 bytes
743 *_buffer++ = *v++;
744 *_buffer++ = *v++;
745 *_buffer++ = *v++;
746 *_buffer++ = *v;
747 }
748
749
750 //----------------------------------------------------------------
751
752
753 static void addIntToBuffer( int _value, unsigned char *&_buffer )
754 {
755 // get pointer
756 unsigned char *v = (unsigned char *) &_value;
757
758 // copy over 4 bytes
759 *_buffer++ = *v++;
760 *_buffer++ = *v++;
761 *_buffer++ = *v++;
762 *_buffer++ = *v;
763 }
764
765
766 //----------------------------------------------------------------
767
768
769 static void addUCharToBuffer( unsigned char _value, unsigned char *&_buffer )
770 {
771 // get pointer
772 unsigned char *v = (unsigned char *) &_value;
773
774 // copy over 1 byte
775 *_buffer++ = *v;
776 }
777
778
779 //----------------------------------------------------------------
780
781
782 void SplatCloudNode::rebuildVBOPositions()
783 {
784 if( (vboPositionsOffset_ == -1) || !splatCloud_.hasPositions() )
785 return;
786
787 # ifdef REPORT_VBO_UPDATES
788 std::cout << "SplatCloudNode::rebuildVBOPositions()" << std::endl;
789 # endif
790
791 // get pointer to buffer
792 unsigned char *buffer = vboData_ + vboPositionsOffset_;
793
794 // for all positions...
795 unsigned int i, num = splatCloud_.numSplats();
796 for( i=0; i<num; ++i )
797 {
798 // add position
799 const Position &p = getPosition( i );
800 buffer = vboData_ + vboPositionsOffset_ + i * vboStride_;
801 addFloatToBuffer( p[0], buffer );
802 addFloatToBuffer( p[1], buffer );
803 addFloatToBuffer( p[2], buffer );
804 }
805 }
806
807
808 //----------------------------------------------------------------
809
810
811 void SplatCloudNode::rebuildVBOColors()
812 {
813 if( (vboColorsOffset_ == -1) || !splatCloud_.hasColors() )
814 return;
815
816 # ifdef REPORT_VBO_UPDATES
817 std::cout << "SplatCloudNode::rebuildVBOColors()" << std::endl;
818 # endif
819
820 // get pointer to buffer
821 unsigned char *buffer = vboData_ + vboColorsOffset_;
822
823 // for all colors...
824 unsigned int i, num = splatCloud_.numSplats();
825 for( i=0; i<num; ++i )
826 {
827 // add color
828 const Color &c = getColor( i );
829 buffer = vboData_ + vboColorsOffset_ + i * vboStride_;
830
831 addUCharToBuffer( c[0], buffer );
832 addUCharToBuffer( c[1], buffer );
833 addUCharToBuffer( c[2], buffer );
834 }
835 }
836
837
838 //----------------------------------------------------------------
839
840
841 void SplatCloudNode::rebuildVBONormals()
842 {
843 if( (vboNormalsOffset_ == -1) || !splatCloud_.hasNormals() )
844 return;
845
846 # ifdef REPORT_VBO_UPDATES
847 std::cout << "SplatCloudNode::rebuildVBONormals()" << std::endl;
848 # endif
849
850 // get pointer to buffer
851 unsigned char *buffer = vboData_ + vboNormalsOffset_;
852
853 // for all normals...
854 unsigned int i, num = splatCloud_.numSplats();
855 for( i=0; i<num; ++i )
856 {
857 // add normal
858 const Normal &n = getNormal( i );
859 buffer = vboData_ + vboNormalsOffset_ + i * vboStride_;
860
861 addFloatToBuffer( n[0], buffer );
862 addFloatToBuffer( n[1], buffer );
863 addFloatToBuffer( n[2], buffer );
864 }
865 }
866
867
868 //----------------------------------------------------------------
869
870
871 void SplatCloudNode::rebuildVBOPointsizes()
872 {
873 if( (vboPointsizesOffset_ == -1) || !splatCloud_.hasPointsizes() )
874 return;
875
876 # ifdef REPORT_VBO_UPDATES
877 std::cout << "SplatCloudNode::rebuildVBOPointsizes()" << std::endl;
878 # endif
879
880 // get pointer to buffer
881 unsigned char *buffer = vboData_ + vboPointsizesOffset_;
882
883 // for all pointsizes...
884 unsigned int i, num = splatCloud_.numSplats();
885 for( i=0; i<num; ++i )
886 {
887 // add pointsize
888 const Pointsize &ps = getPointsize( i );
889 buffer = vboData_ + vboPointsizesOffset_ + i * vboStride_;
890
891 addFloatToBuffer(ps, buffer);
892 }
893 }
894
895
896 //----------------------------------------------------------------
897
898
899 void SplatCloudNode::rebuildVBOSelections()
900 {
901 if( (vboSelectionsOffset_ == -1) || !splatCloud_.hasSelections() )
902 return;
903
904 # ifdef REPORT_VBO_UPDATES
905 std::cout << "SplatCloudNode::rebuildVBOSelections()" << std::endl;
906 # endif
907
908 // get pointer to buffer
909 unsigned char *buffer = vboData_ + vboSelectionsOffset_;
910
911 // for all selections...
912 unsigned int i, num = splatCloud_.numSplats();
913 for( i=0; i<num; ++i )
914 {
915 const bool &s = getSelection( i );
916 buffer = vboData_ + vboSelectionsOffset_ + i * vboStride_;
917
918 addFloatToBuffer((s ? 1.0f : 0.0f), buffer);
919 }
920 }
921
922
923 //----------------------------------------------------------------
924
925
926 void SplatCloudNode::rebuildVBOPickColors( GLState &_state )
927 {
928 if( (vboPickColorsOffset_ == -1) || !splatCloud_.hasPositions() )
929 return;
930
931 # ifdef REPORT_VBO_UPDATES
932 std::cout << "SplatCloudNode::rebuildVBOPickColors()" << std::endl;
933 # endif
934
935 // get pointer to buffer
936 unsigned char *buffer = vboData_ + vboPickColorsOffset_;
937
938 // for all pick colors...
939 unsigned int i, num = splatCloud_.numSplats();
940 for( i=0; i<num; ++i )
941 {
942 // add pick color
943 const Vec4uc &pc = _state.pick_get_name_color( i );
944 buffer = vboData_ + vboPickColorsOffset_ + i * vboStride_;
945
946 addUCharToBuffer( pc[0], buffer );
947 addUCharToBuffer( pc[1], buffer );
948 addUCharToBuffer( pc[2], buffer );
949 addUCharToBuffer( pc[3], buffer );
950 }
951 }
952
953
954 //================================================================
955
956
957 } // namespace SceneGraph
958 } // namespace ACG
ACG::GLState::color_picking
bool color_picking() const
Is color picking active?
Definition: GLState.cc:1141
ACG::VertexDeclaration::setVertexStride
void setVertexStride(unsigned int _stride)
Definition: VertexDeclaration.cc:564
ACG::RenderObject::initFromState
void initFromState(GLState *_glState)
Initializes a RenderObject instance.
Definition: RenderObject.cc:61
SplatCloud::positions
Position & positions(int _idx)
Get a reference of the predefined property&#39;s value.
Definition: SplatCloud.hh:631
ACG::RenderObject::setUniform
void setUniform(const char *_name, GLint _value)
set values for int uniforms
Definition: RenderObject.cc:413
ACG::VERTEX_USAGE_SHADER_INPUT
defined by user via VertexElement::shaderInputName_
Definition: VertexDeclaration.hh:71
ACG::GLState
Definition: GLState.hh:213
SplatCloud::numSplats
unsigned int numSplats() const
Get the number of splats.
Definition: SplatCloud.hh:179
ACG
Namespace providing different geometric functions concerning angles.
Definition: BaseObjectData.hh:68
ACG::SceneGraph::DrawModes::DrawMode::containsAtomicDrawMode
bool containsAtomicDrawMode(const DrawMode &_atomicDrawMode) const
Check whether an Atomic DrawMode is active in this draw Mode.
Definition: DrawModes.cc:520
SplatCloud::hasSelections
bool hasSelections() const
Return the availability of the predefined property.
Definition: SplatCloud.hh:613
SplatCloud
Definition: SplatCloud.hh:79
ACG::SceneGraph::ACG::GLState::disable
static void disable(GLenum _cap, bool _warnRemoved=true)
replaces glDisable, but supports locking
ACG::GLState::get_viewport
void get_viewport(int &_left, int &_bottom, int &_width, int &_height) const
get viewport
Definition: GLState.hh:816
ACG::SceneGraph::ACG::GLState::enableClientState
static void enableClientState(GLenum _cap)
replaces glEnableClientState, supports locking
ACG::RenderObject::shaderDesc
ShaderGenDesc shaderDesc
Drawmode and other shader params.
Definition: RenderObject.hh:225
ACG::GLState::pick_current_index
size_t pick_current_index() const
Returns the current color picking index (can be used for caching)
Definition: GLState.cc:1131
ACG::SceneGraph::SplatCloudNode::splatCloud_
const SplatCloud & splatCloud_
reference to class containing all the data
Definition: SplatCloudNode.hh:194
OpenMesh::VectorT
Definition: Vector11T.hh:83
ACG::SceneGraph::ACG::GLState::bindBufferARB
static void bindBufferARB(GLenum _target, GLuint _buffer)
same function as bindBuffer
Definition: MeshNode2T_impl.hh:573
OpenMesh::VectorT::maximize
vector_type & maximize(const vector_type &_rhs)
maximize values: same as *this = max(*this, _rhs), but faster
Definition: Vector11T.hh:568
ACG::RenderObject::vertexBuffer
GLuint vertexBuffer
VBO, IBO ids, ignored if VAO is provided.
Definition: RenderObject.hh:162
SplatCloud::hasPositions
bool hasPositions() const
Return the availability of the predefined property.
Definition: SplatCloud.hh:607
ACG::GLState::depthFunc
const GLenum & depthFunc() const
get glDepthFunc() that is supposed to be active
Definition: GLState.cc:941
ACG::GLState::pick_get_name_color
Vec4uc pick_get_name_color(size_t _idx)
Definition: GLState.cc:1068
ACG::VertexDeclaration::clear
void clear()
Definition: VertexDeclaration.cc:570
ACG::SceneGraph::ACG::GLState::disableClientState
static void disableClientState(GLenum _cap)
replaces glDisableClientState, supports locking
ACG::IRenderer
Definition: IRenderer.hh:78
SceneGraph
Definition: QtPrincipalAxisDialog.hh:67
SplatCloud::hasColors
bool hasColors() const
Return the availability of the predefined property.
Definition: SplatCloud.hh:608
ACG::VERTEX_USAGE_NORMAL
"inNormal"
Definition: VertexDeclaration.hh:66
ACG::VERTEX_USAGE_TEXCOORD
"inTexCoord"
Definition: VertexDeclaration.hh:67
ACG::SceneGraph::PickTarget
PickTarget
What target to use for picking.
Definition: PickTarget.hh:73
ACG::SceneGraph::SplatCloudNode::~SplatCloudNode
~SplatCloudNode()
destructor
Definition: SplatCloudNode.cc:122
ACG::SceneGraph::ACG::GLState::colorPointer
static void colorPointer(GLint _size, GLenum _type, GLsizei _stride, const GLvoid *_pointer)
replaces glColorPointer, supports locking
ACG::Vec3f
VectorT< float, 3 > Vec3f
Definition: VectorT.hh:119
ACG::GLState::inverse_projection
const GLMatrixd & inverse_projection() const
get inverse projection matrix
Definition: GLState.hh:806
ACG::VERTEX_USAGE_POSITION
"inPosition"
Definition: VertexDeclaration.hh:65
ACG::GLMatrixT< double >
ACG::VertexDeclaration::addElement
void addElement(const VertexElement *_pElement)
Definition: VertexDeclaration.cc:115
ACG::SceneGraph::PICK_ANYTHING
pick any of the prior targets (should be implemented for all nodes)
Definition: PickTarget.hh:84
ACG::GLState::pick_set_maximum
bool pick_set_maximum(size_t _idx)
Set the maximal number of primitives/components of your object.
Definition: GLState.cc:1051
ACG::SceneGraph::PICK_VERTEX
picks verices (may not be implemented for all nodes)
Definition: PickTarget.hh:82
OpenMesh::VectorT::minimize
vector_type & minimize(const vector_type &_rhs)
minimize values: same as *this = min(*this, _rhs), but faster
Definition: Vector11T.hh:540
ACG::SceneGraph::SplatCloudNode::boundingBox
void boundingBox(ACG::Vec3d &_bbMin, ACG::Vec3d &_bbMax) override
update bounding box
Definition: SplatCloudNode.cc:131
SplatCloud::hasNormals
bool hasNormals() const
Return the availability of the predefined property.
Definition: SplatCloud.hh:609
ACG::RenderObject::vertexDecl
const VertexDeclaration * vertexDecl
Defines the vertex buffer layout, ignored if VAO is provided.
Definition: RenderObject.hh:208
ACG::SceneGraph::SplatCloudNode::SplatCloudNode
SplatCloudNode(const SplatCloud &_splatCloud, BaseNode *_parent=0, std::string _name="<SplatCloudNode>")
constructor
Definition: SplatCloudNode.cc:83
ACG::SceneGraph::BaseNode
Definition: BaseNode.hh:104
ACG::SceneGraph::ACG::GLState::normalPointer
static void normalPointer(GLenum _type, GLsizei _stride, const GLvoid *_pointer)
replaces glNormalPointer, supports locking
ACG::SceneGraph::SplatCloudNode::vboStructureModified
bool vboStructureModified() const
returns true iff the internal block structure of the VBO has to be changed
Definition: SplatCloudNode.hh:255
ACG::SceneGraph::ACG::GLState::texcoordPointer
static void texcoordPointer(GLint _size, GLenum _type, GLsizei _stride, const GLvoid *_pointer)
replaces glTexcoordPointer, supports locking
ACG::IRenderer::addRenderObject
virtual void addRenderObject(RenderObject *_renderObject)
Callback for the scenegraph nodes, which send new render objects via this function.
Definition: IRenderer.cc:104
ACG::SceneGraph::ACG::GLState::vertexPointer
static void vertexPointer(GLint _size, GLenum _type, GLsizei _stride, const GLvoid *_pointer)
replaces glVertexPointer, supports locking
ACG::SceneGraph::DrawModes::DrawMode
Specifies a DrawMode.
Definition: DrawModes.hh:288
ACG::SceneGraph::SplatCloudNode::getPosition
const Position & getPosition(int _idx) const
if the data array exists, the entry with the given index is returned, otherwise the default value is ...
Definition: SplatCloudNode.hh:167
ACG::VERTEX_USAGE_COLOR
"inColor"
Definition: VertexDeclaration.hh:68
ACG::SceneGraph::SplatCloudNode::positionsModified_
bool positionsModified_
marks if parts of the data has been modified
Definition: SplatCloudNode.hh:199
ACG::GLState::modelview
const GLMatrixd & modelview() const
get modelview matrix
Definition: GLState.hh:791
ACG::SceneGraph::ACG::GLState::enable
static void enable(GLenum _cap, bool _warnRemoved=true)
replaces glEnable, but supports locking
ACG::SceneGraph::SplatCloudNode::defaultColor_
Color defaultColor_
the default values will be used when the specific array is not present
Definition: SplatCloudNode.hh:220
ACG::SceneGraph::SplatCloudNode::draw
void draw(GLState &_state, const DrawModes::DrawMode &_drawMode) override
draw the SplatCloud
Definition: SplatCloudNode.cc:158
ACG::SceneGraph::SplatCloudNode::vboPositionsOffset_
int vboPositionsOffset_
offsets relative to vboData_ or -1 if not present in VBO
Definition: SplatCloudNode.hh:245
SplatCloud::hasPointsizes
bool hasPointsizes() const
Return the availability of the predefined property.
Definition: SplatCloud.hh:610
ACG::SceneGraph::SplatCloudNode::vboModified
bool vboModified() const
return true iff any of the data values in the VBO has to be changed
Definition: SplatCloudNode.hh:207
ACG::GLState::projection
const GLMatrixd & projection() const
get projection matrix
Definition: GLState.hh:786
ACG::RenderObject
Interface class between scenegraph and renderer.
Definition: RenderObject.hh:98
ACG::SceneGraph::Material
Definition: MaterialNode.hh:79
ACG::SceneGraph::SplatCloudNode::pick
void pick(GLState &_state, PickTarget _target) override
picking
Definition: SplatCloudNode.cc:568
ACG::SceneGraph::ACG::GLState::depthFunc
const GLenum & depthFunc() const
get glDepthFunc() that is supposed to be active
ACG::SceneGraph::SplatCloudNode::getRenderObjects
void getRenderObjects(IRenderer *_renderer, GLState &_state, const DrawModes::DrawMode &_drawMode, const Material *_mat) override
create render objects
Definition: SplatCloudNode.cc:320