Developer Documentation
Loading...
Searching...
No Matches
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
68namespace ACG {
69namespace SceneGraph {
70
71//== STATIC MEMBER VARIABLES =====================================
72
73
74const SplatCloudNode::Position SplatCloudNode::DEFAULT_POSITION (0,0,0);
75const SplatCloudNode::Index SplatCloudNode::DEFAULT_INDEX ( -1);
76const SplatCloudNode::Viewlist SplatCloudNode::DEFAULT_VIEWLIST ( 0.0);
77const SplatCloudNode::Selection SplatCloudNode::DEFAULT_SELECTION(false);
78
79
80//== IMPLEMENTATION ==============================================
81
82
83SplatCloudNode::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
123{
124 destroyVBO();
125}
126
127
128//----------------------------------------------------------------
129
130
132{
133 ACG::Vec3f bbMin( FLT_MAX, FLT_MAX, FLT_MAX );
134 ACG::Vec3f bbMax(-FLT_MAX,-FLT_MAX,-FLT_MAX );
135
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
158void 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
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
320void 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
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
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
599void 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
616void 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
632void 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
737static 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
753static 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
769static 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
782void SplatCloudNode::rebuildVBOPositions()
783{
785 return;
786
787# ifdef REPORT_VBO_UPDATES
788 std::cout << "SplatCloudNode::rebuildVBOPositions()" << std::endl;
789# endif
790
791
792 // for all positions...
793 unsigned int num = splatCloud_.numSplats();
794 for( unsigned int i=0; i<num; ++i )
795 {
796 // add position
797 const Position &p = getPosition( i );
798
799 // get pointer to buffer
800 unsigned char *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
812void SplatCloudNode::rebuildVBOColors()
813{
814 if( (vboColorsOffset_ == -1) || !splatCloud_.hasColors() )
815 return;
816
817# ifdef REPORT_VBO_UPDATES
818 std::cout << "SplatCloudNode::rebuildVBOColors()" << std::endl;
819# endif
820
821 // for all colors...
822 unsigned int num = splatCloud_.numSplats();
823 for( unsigned int i=0; i<num; ++i )
824 {
825 // add color
826 const Color &c = getColor( i );
827
828 // get pointer to buffer
829 unsigned char *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
841void 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 // for all normals...
851 unsigned int num = splatCloud_.numSplats();
852 for( unsigned int i=0; i<num; ++i )
853 {
854 // add normal
855 const Normal &n = getNormal( i );
856
857 // get pointer to buffer
858 unsigned char *buffer = vboData_ + vboNormalsOffset_ + i * vboStride_;
859
860 addFloatToBuffer( n[0], buffer );
861 addFloatToBuffer( n[1], buffer );
862 addFloatToBuffer( n[2], buffer );
863 }
864}
865
866
867//----------------------------------------------------------------
868
869
870void SplatCloudNode::rebuildVBOPointsizes()
871{
872 if( (vboPointsizesOffset_ == -1) || !splatCloud_.hasPointsizes() )
873 return;
874
875# ifdef REPORT_VBO_UPDATES
876 std::cout << "SplatCloudNode::rebuildVBOPointsizes()" << std::endl;
877# endif
878
879 // for all pointsizes...
880 unsigned int num = splatCloud_.numSplats();
881 for( unsigned int i=0; i<num; ++i )
882 {
883 // add pointsize
884 const Pointsize &ps = getPointsize( i );
885
886 // get pointer to buffer
887 unsigned char *buffer = vboData_ + vboPointsizesOffset_ + i * vboStride_;
888
889 addFloatToBuffer(ps, buffer);
890 }
891}
892
893
894//----------------------------------------------------------------
895
896
897void SplatCloudNode::rebuildVBOSelections()
898{
899 if( (vboSelectionsOffset_ == -1) || !splatCloud_.hasSelections() )
900 return;
901
902# ifdef REPORT_VBO_UPDATES
903 std::cout << "SplatCloudNode::rebuildVBOSelections()" << std::endl;
904# endif
905
906 // for all selections...
907 unsigned int num = splatCloud_.numSplats();
908 for( unsigned int i=0; i<num; ++i )
909 {
910 const bool &s = getSelection( i );
911
912 // get pointer to buffer
913 unsigned char *buffer = vboData_ + vboSelectionsOffset_ + i * vboStride_;
914
915 addFloatToBuffer((s ? 1.0f : 0.0f), buffer);
916 }
917}
918
919
920//----------------------------------------------------------------
921
922
923void SplatCloudNode::rebuildVBOPickColors( GLState &_state )
924{
925 if( (vboPickColorsOffset_ == -1) || !splatCloud_.hasPositions() )
926 return;
927
928# ifdef REPORT_VBO_UPDATES
929 std::cout << "SplatCloudNode::rebuildVBOPickColors()" << std::endl;
930# endif
931
932 // for all pick colors...
933 unsigned int num = splatCloud_.numSplats();
934 for( unsigned int i=0; i<num; ++i )
935 {
936 // add pick color
937 const Vec4uc &pc = _state.pick_get_name_color( i );
938
939 // get pointer to buffer
940 unsigned char *buffer = vboData_ + vboPickColorsOffset_ + i * vboStride_;
941
942 addUCharToBuffer( pc[0], buffer );
943 addUCharToBuffer( pc[1], buffer );
944 addUCharToBuffer( pc[2], buffer );
945 addUCharToBuffer( pc[3], buffer );
946 }
947}
948
949
950//================================================================
951
952
953} // namespace SceneGraph
954} // namespace ACG
static void disableClientState(GLenum _cap)
replaces glDisableClientState, supports locking
Definition GLState.cc:1584
static void colorPointer(GLint _size, GLenum _type, GLsizei _stride, const GLvoid *_pointer)
replaces glColorPointer, supports locking
Definition GLState.cc:2005
static void vertexPointer(GLint _size, GLenum _type, GLsizei _stride, const GLvoid *_pointer)
replaces glVertexPointer, supports locking
Definition GLState.cc:1961
static void enable(GLenum _cap, bool _warnRemoved=true)
replaces glEnable, but supports locking
Definition GLState.cc:1507
static void bindBufferARB(GLenum _target, GLuint _buffer)
same function as bindBuffer
Definition GLState.hh:579
static void normalPointer(GLenum _type, GLsizei _stride, const GLvoid *_pointer)
replaces glNormalPointer, supports locking
Definition GLState.cc:1983
const GLMatrixd & modelview() const
get modelview matrix
Definition GLState.hh:816
bool color_picking() const
Is color picking active?
Definition GLState.cc:1141
static void enableClientState(GLenum _cap)
replaces glEnableClientState, supports locking
Definition GLState.cc:1570
bool pick_set_maximum(size_t _idx)
Set the maximal number of primitives/components of your object.
Definition GLState.cc:1051
const GLMatrixd & projection() const
get projection matrix
Definition GLState.hh:811
static void texcoordPointer(GLint _size, GLenum _type, GLsizei _stride, const GLvoid *_pointer)
replaces glTexcoordPointer, supports locking
Definition GLState.cc:2027
static void disable(GLenum _cap, bool _warnRemoved=true)
replaces glDisable, but supports locking
Definition GLState.cc:1527
size_t pick_current_index() const
Returns the current color picking index (can be used for caching)
Definition GLState.cc:1131
void get_viewport(int &_left, int &_bottom, int &_width, int &_height) const
get viewport
Definition GLState.hh:841
const GLenum & depthFunc() const
get glDepthFunc() that is supposed to be active
Definition GLState.cc:941
const GLMatrixd & inverse_projection() const
get inverse projection matrix
Definition GLState.hh:831
virtual void addRenderObject(RenderObject *_renderObject)
Callback for the scenegraph nodes, which send new render objects via this function.
Definition IRenderer.cc:104
bool containsAtomicDrawMode(const DrawMode &_atomicDrawMode) const
Check whether an Atomic DrawMode is active in this draw Mode.
Definition DrawModes.cc:510
int vboPositionsOffset_
offsets relative to vboData_ or -1 if not present in VBO
void draw(GLState &_state, const DrawModes::DrawMode &_drawMode) override
draw the SplatCloud
bool positionsModified_
marks if parts of the data has been modified
void pick(GLState &_state, PickTarget _target) override
picking
const SplatCloud & splatCloud_
reference to class containing all the data
SplatCloudNode(const SplatCloud &_splatCloud, BaseNode *_parent=0, std::string _name="<SplatCloudNode>")
constructor
bool vboStructureModified() const
returns true iff the internal block structure of the VBO has to be changed
Color defaultColor_
the default values will be used when the specific array is not present
void boundingBox(ACG::Vec3d &_bbMin, ACG::Vec3d &_bbMax) override
update bounding box
const Position & getPosition(int _idx) const
if the data array exists, the entry with the given index is returned, otherwise the default value is ...
void getRenderObjects(IRenderer *_renderer, GLState &_state, const DrawModes::DrawMode &_drawMode, const Material *_mat) override
create render objects
bool vboModified() const
return true iff any of the data values in the VBO has to be changed
void addElement(const VertexElement *_pElement)
void setVertexStride(unsigned int _stride)
vector_type & maximize(const vector_type &_rhs)
maximize values: same as *this = max(*this, _rhs), but faster
Definition Vector11T.hh:588
vector_type & minimize(const vector_type &_rhs)
minimize values: same as *this = min(*this, _rhs), but faster
Definition Vector11T.hh:560
bool hasPointsizes() const
Return the availability of the predefined property.
unsigned int numSplats() const
Get the number of splats.
bool hasPositions() const
Return the availability of the predefined property.
Position & positions(int _idx)
Get a reference of the predefined property's value.
bool hasSelections() const
Return the availability of the predefined property.
bool hasNormals() const
Return the availability of the predefined property.
bool hasColors() const
Return the availability of the predefined property.
PickTarget
What target to use for picking.
Definition PickTarget.hh:74
@ PICK_ANYTHING
pick any of the prior targets (should be implemented for all nodes)
Definition PickTarget.hh:84
@ PICK_VERTEX
picks verices (may not be implemented for all nodes)
Definition PickTarget.hh:82
Namespace providing different geometric functions concerning angles.
VectorT< float, 3 > Vec3f
Definition VectorT.hh:119
@ VERTEX_USAGE_NORMAL
"inNormal"
@ VERTEX_USAGE_COLOR
"inColor"
@ VERTEX_USAGE_POSITION
"inPosition"
@ VERTEX_USAGE_TEXCOORD
"inTexCoord"
@ VERTEX_USAGE_SHADER_INPUT
defined by user via VertexElement::shaderInputName_
Interface class between scenegraph and renderer.
ShaderGenDesc shaderDesc
Drawmode and other shader params.
const VertexDeclaration * vertexDecl
Defines the vertex buffer layout, ignored if VAO is provided.
GLuint vertexBuffer
VBO, IBO ids, ignored if VAO is provided.
void setUniform(const char *_name, GLint _value)
set values for int uniforms
void initFromState(GLState *_glState)
Initializes a RenderObject instance.