Developer Documentation
Loading...
Searching...
No Matches
PolyLineNodeT_impl.hh
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
47//=============================================================================
48//
49// CLASS PolyLineNodeT - IMPLEMENTATION
50//
51//=============================================================================
52
53#define ACG_POLYLINENODET_C
54
55//== INCLUDES =================================================================
56
57#include "PolyLineNodeT.hh"
58#include <ACG/GL/gl.hh>
59#include <ACG/GL/ShaderCache.hh>
60#include <ACG/Utils/VSToolsT.hh>
61#include <vector>
62
63//== NAMESPACES ===============================================================
64
65namespace ACG {
66namespace SceneGraph {
67
68//== IMPLEMENTATION ==========================================================
69
71template <class PolyLine>
72PolyLineNodeT<PolyLine>::PolyLineNodeT(PolyLine& _pl, BaseNode* _parent, std::string _name) :
73 BaseNode(_parent, _name),
74 polyline_(_pl),
75 updateVBO_(true),
76 sphere_(0)
77
78{
79
80 // Initialize our local draw mode references
82 ACG::SceneGraph::DrawModes::DrawModeProperties(ACG::SceneGraph::DrawModes::PRIMITIVE_POLYGON,
85
86 POINTS_SPHERES_SCREEN = DrawModes::DrawMode(ACG::SceneGraph::DrawModes::addDrawMode("Points (as Spheres, constant screen size)",
87 ACG::SceneGraph::DrawModes::DrawModeProperties(ACG::SceneGraph::DrawModes::PRIMITIVE_POLYGON,
90
91 // Initial default draw mode
93}
94
95//----------------------------------------------------------------------------
96
97template <class PolyLine>
102
103//----------------------------------------------------------------------------
104
105template <class PolyLine>
106void
108boundingBox(Vec3d& _bbMin, Vec3d& _bbMax)
109{
110 for (unsigned int i=0; i< polyline_.n_vertices(); ++i)
112 _bbMin.minimize(polyline_.point(i));
113 _bbMax.maximize(polyline_.point(i));
115}
116
118//----------------------------------------------------------------------------
119
120
121template <class PolyLine>
124availableDrawModes() const
125{
126 return (DrawModes::WIREFRAME | DrawModes::POINTS | DrawModes::POINTS_COLORED | POINTS_SPHERES | POINTS_SPHERES_SCREEN | DrawModes::EDGES_COLORED);
127}
128
129
130//----------------------------------------------------------------------------
131
132
133template <class PolyLine>
134void
136draw(GLState& _state, const DrawModes::DrawMode& _drawMode)
137{
138 // Block if we do not have any vertices
139 if ( polyline_.n_vertices() == 0 )
140 return;
141
142 // Update the vbo only if required.
143 if ( updateVBO_ )
144 updateVBO();
145
146 ACG::GLState::disable(GL_LIGHTING);
147 ACG::GLState::disable(GL_TEXTURE_2D);
148
149 // Bind the vertex array
150 vbo_.bind();
151
152 ACG::Vec4f color = _state.ambient_color() + _state.diffuse_color();
153
154 // draw points
155 if (_drawMode & DrawModes::POINTS || _drawMode & DrawModes::POINTS_COLORED)
156 {
157 vertexDecl_.activateFixedFunction();
158
159 // draw selection
160 if( polyline_.vertex_selections_available() && !selectedVertexIndexBuffer_.empty())
161 {
162 // save old values
163 float point_size_old = _state.point_size();
164 _state.set_color( Vec4f(1,0,0,1) );
165 _state.set_point_size(point_size_old+4);
166
167 glDrawElements(GL_POINTS, selectedVertexIndexBuffer_.size(), GL_UNSIGNED_INT, &(selectedVertexIndexBuffer_[0]));
168
169 _state.set_point_size(point_size_old);
170 }
171
172 _state.set_color( color );
173
174
175 if (_drawMode & DrawModes::POINTS_COLORED)
176 {
177 vertexDecl_.deactivateFixedFunction();
178 vertexDeclVCol_.activateFixedFunction();
179 }
180
181 // Draw all vertices (don't care about selection)
182 glDrawArrays(GL_POINTS, 0, polyline_.n_vertices());
183
185 vertexDeclVCol_.deactivateFixedFunction();
186 else
187 vertexDecl_.deactivateFixedFunction();
188 }
189
190 // draw line segments
191 if (_drawMode & DrawModes::WIREFRAME) {
192 vertexDecl_.activateFixedFunction();
193
194 // draw selection
195 if (polyline_.edge_selections_available() && !selectedEdgeIndexBuffer_.empty()) {
196 // save old values
197 float line_width_old = _state.line_width();
198 _state.set_color(Vec4f(1, 0, 0, 1));
199 _state.set_line_width(2 * line_width_old);
200
201 glDrawElements(GL_LINES, selectedEdgeIndexBuffer_.size(), GL_UNSIGNED_INT, &(selectedEdgeIndexBuffer_[0]));
202
203 _state.set_line_width(line_width_old);
204 }
205
206 _state.set_color( color );
207
208 if ( polyline_.is_closed() )
209 glDrawArrays(GL_LINE_STRIP, 0, polyline_.n_vertices() + 1);
210 else
211 glDrawArrays(GL_LINE_STRIP, 0, polyline_.n_vertices());
212
213 vertexDecl_.deactivateFixedFunction();
214 }
215
216
217 if (_drawMode & DrawModes::EDGES_COLORED) {
218 vertexDecl_.activateFixedFunction();
219
220 // draw selection
221 if (polyline_.edge_selections_available() && !selectedEdgeIndexBuffer_.empty()) {
222 // save old values
223 float line_width_old = _state.line_width();
224 _state.set_color(Vec4f(1, 0, 0, 1));
225 _state.set_line_width(2 * line_width_old);
226
227 glDrawElements(GL_LINES, selectedEdgeIndexBuffer_.size(), GL_UNSIGNED_INT, &(selectedEdgeIndexBuffer_[0]));
228
229 _state.set_line_width(line_width_old);
230 }
231
232 vertexDecl_.deactivateFixedFunction();
233
234 _state.set_color(color);
235
236
237 vertexDeclECol_.activateFixedFunction();
238 if (polyline_.is_closed())
239 glDrawArrays(GL_LINE_STRIP, 0, polyline_.n_vertices() + 1);
240 else
241 glDrawArrays(GL_LINE_STRIP, 0, polyline_.n_vertices());
242
243 vertexDeclECol_.deactivateFixedFunction();
244 }
245
246
247 // draw normals
248 if (polyline_.vertex_normals_available()) {
249 double avg_len = polyline_.n_edges() > 0 ? (polyline_.length() / polyline_.n_edges() * 0.75) : 0;
250 std::vector<Point> ps;
251 for (unsigned int i = 0; i < polyline_.n_vertices(); ++i) {
252 ps.push_back(polyline_.point(i));
253 ps.push_back(polyline_.point(i) + polyline_.vertex_normal(i) * avg_len);
254 if (polyline_.vertex_binormals_available())
255 ps.push_back(polyline_.point(i) + polyline_.vertex_binormal(i) * avg_len);
256 }
257
258 // Disable the big buffer and switch to in memory buffer
259 vbo_.unbind();
261
262 float line_width_old = _state.line_width();
263 _state.set_color( Vec4f(0.8f, 0.f, 0.f, 1.f) );
264 _state.set_line_width(1);
265
266 int stride = polyline_.vertex_binormals_available() ? 3 : 2;
267 glBegin(GL_LINES);
268 for (unsigned int i = 0; i < polyline_.n_vertices(); ++i) {
269 glArrayElement(stride * i);
270 glArrayElement(stride * i + 1);
271 }
272 glEnd();
273
274 if (polyline_.vertex_binormals_available()) {
275 _state.set_color( Vec4f(0.f, 0.f, 0.8f, 1.f) );
276 glBegin(GL_LINES);
277 for (unsigned int i = 0; i < polyline_.n_vertices(); ++i) {
278 glArrayElement(stride * i);
279 glArrayElement(stride * i + 2);
280 }
281 glEnd();
282 }
283
284 _state.set_line_width(line_width_old);
285 }
286
287 vbo_.unbind();
288
289 //Disable the vertex array
290 ACG::GLState::disableClientState(GL_VERTEX_ARRAY);
291
292 // draw vertices as spheres, using the radius given in the polyline
293 if (_drawMode & POINTS_SPHERES)
294 {
295 // create sphere if not yet done
296 if(!sphere_)
297 sphere_ = new GLSphere(10,10);
298
299 if( polyline_.vertex_selections_available())
300 {
301 for(unsigned int i=0; i<polyline_.n_vertices(); ++i)
302 {
303 if(polyline_.vertex_selected(i))
304 _state.set_color( Vec4f(1,0,0,1) );
305 else
306 _state.set_color( color );
307
308 sphere_->draw(_state, _state.point_size(), (Vec3f)polyline_.point(i));
309 }
310 }
311 else
312 {
313 _state.set_color( color );
314 for(unsigned int i=0; i<polyline_.n_vertices(); ++i)
315 sphere_->draw(_state, _state.point_size(), (Vec3f)polyline_.point(i));
316 }
317 }
318 // draw vertices as spheres with constant size on screen
319 if (_drawMode & POINTS_SPHERES_SCREEN)
320 {
321 // create sphere if not yet done
322 if(!sphere_)
323 sphere_ = new GLSphere(10,10);
324
325 // precompute desired radius of projected sphere
326 double r = 0.5*_state.point_size() / double(_state.viewport_height()) * 2.0 * tan(0.5*_state.fovy());
327
328 if( polyline_.vertex_selections_available())
329 {
330 for(unsigned int i=0; i<polyline_.n_vertices(); ++i)
331 {
332 if(polyline_.vertex_selected(i))
333 _state.set_color( Vec4f(1,0,0,1) );
334 else
335 _state.set_color( color );
336
337 // compute radius in 3D
338 const Vec3d p = (Vec3d)polyline_.point(i) - _state.eye();
339 const double l = (p|_state.viewing_direction());
340 sphere_->draw(_state, r*l, (Vec3f)polyline_.point(i));
341 }
342 }
343 else
344 {
345 _state.set_color( color );
346 for(unsigned int i=0; i<polyline_.n_vertices(); ++i)
347 {
348 // compute radius in 3D
349 const Vec3d p = (Vec3d)polyline_.point(i) - _state.eye();
350 const double l = (p|_state.viewing_direction());
351 sphere_->draw(_state, r*l, (Vec3f)polyline_.point(i));
352 }
353
354 }
355 }
356}
357
358//----------------------------------------------------------------------------
359
360
361template <class PolyLine>
362void
364pick(GLState& _state, PickTarget _target)
365{
366 if ( polyline_.n_vertices() == 0 )
367 return;
368
369 // Bind the vertex array
370 ACG::GLState::bindBuffer(GL_ARRAY_BUFFER_ARB, 0);
371 ACG::GLState::vertexPointer( &(polyline_.points())[0] );
372 ACG::GLState::enableClientState(GL_VERTEX_ARRAY);
373
374 unsigned int n_end = polyline_.n_edges()+1;
375 if( !polyline_.is_closed()) --n_end;
376
377 // (draw lines slightly in front of everything else)
378 //disabled right now because of rendering artifacts.
379 //This probably doesn't make sense anyways since the lines are drawn as cylinders and therefore have a width
380 // glDepthRange(0.0,0.99)
381
382 switch (_target)
383 {
384 case PICK_VERTEX:
385 {
386 _state.pick_set_maximum (polyline_.n_vertices());
387 if (drawMode() & DrawModes::POINTS)
388 pick_vertices( _state);
389
390 if (drawMode() & POINTS_SPHERES)
391 pick_spheres( _state);
392
393 if (drawMode() & POINTS_SPHERES_SCREEN)
394 pick_spheres_screen( _state);
395
396 break;
397 }
398
399 case PICK_EDGE:
400 {
401 _state.pick_set_maximum (n_end);
402 pick_edges(_state, 0);
403 break;
404 }
405
406 case PICK_ANYTHING:
407 {
408 _state.pick_set_maximum (polyline_.n_vertices() + n_end);
409
410 if (drawMode() & DrawModes::POINTS)
411 pick_vertices( _state);
412
413 if (drawMode() & POINTS_SPHERES)
414 pick_spheres( _state);
415
416 if (drawMode() & POINTS_SPHERES_SCREEN)
417 pick_spheres_screen( _state);
418
419 pick_edges( _state, polyline_.n_vertices());
420 break;
421 }
422
423 default:
424 break;
425 }
426
427 //see above
428 // glDepthRange(0.0,1.0)
429
430 //Disable the vertex array
431 ACG::GLState::disableClientState(GL_VERTEX_ARRAY);
432
433}
434
435
436//----------------------------------------------------------------------------
437
438
439template <class PolyLine>
440void
442pick_vertices( GLState& _state )
443{
444 if (!polyline_.n_vertices())
445 return;
446
447 float point_size_old = _state.point_size();
448 glPointSize(18);
449
450 glDepthRange(0.0, 0.999999);
451
452 static ShaderGenDesc desc;
453 desc.vertexTemplateFile = "Picking/pick_vertices_vs.glsl";
454 desc.fragmentTemplateFile = "Picking/pick_vertices_fs.glsl";
455 GLSL::Program* pickShader = ACG::ShaderCache::getInstance()->getProgram(&desc, nullptr);
456
457 if (pickShader && pickShader->isLinked())
458 {
459 // Update the vbo only if required.
460 if (updateVBO_)
461 updateVBO();
462
463 // Bind the vertex array
464 vbo_.bind();
465
466 int pickOffsetIndex = int(_state.pick_current_index());
467
468 vertexDecl_.activateShaderPipeline(pickShader);
469
470 pickShader->use();
471
472 ACG::GLMatrixf transform = _state.projection() * _state.modelview();
473
474 pickShader->setUniform("mWVP", transform);
475 pickShader->setUniform("pickVertexOffset", pickOffsetIndex);
476
477 glDrawArrays(GL_POINTS, 0, polyline_.n_vertices());
478
479 vertexDecl_.deactivateShaderPipeline(pickShader);
480 pickShader->disable();
481
482
483 vbo_.unbind();
484 }
485 else
486 {
487 for (unsigned int i = 0; i < polyline_.n_vertices(); ++i) {
488 _state.pick_set_name(i);
489 glBegin(GL_POINTS);
490 glArrayElement(i);
491 glEnd();
492 }
493 }
494
495 glDepthRange(0.0, 1.0);
496
497
498
499 glPointSize(point_size_old);
500}
501
502
503//----------------------------------------------------------------------------
504
505
506template <class PolyLine>
507void
508PolyLineNodeT<PolyLine>::
509pick_spheres( GLState& _state )
510{
511 if(!sphere_)
512 sphere_ = new GLSphere(10,10);
513
514 _state.pick_set_name(0);
515
516 for(unsigned int i=0; i<polyline_.n_vertices(); ++i)
517 {
518 _state.pick_set_name (i);
519 sphere_->draw(_state, _state.point_size(), (Vec3f)polyline_.point(i));
520 }
521}
522
523//----------------------------------------------------------------------------
524
525
526template <class PolyLine>
527void
528PolyLineNodeT<PolyLine>::
529pick_spheres_screen( GLState& _state )
530{
531 if(!sphere_)
532 sphere_ = new GLSphere(10,10);
533
534 _state.pick_set_name(0);
535
536 // precompute desired radius of projected sphere
537 double r = 0.5*_state.point_size()/double(_state.viewport_height())*2.0*tan(0.5*_state.fovy());
538
539 for(unsigned int i=0; i<polyline_.n_vertices(); ++i)
540 {
541 _state.pick_set_name (i);
542 // compute radius in 3D
543 const Vec3d p = (Vec3d)polyline_.point(i) - _state.eye();
544 double l = (p|_state.viewing_direction());
545 sphere_->draw(_state, r*l, (Vec3f)polyline_.point(i));
546
547// ToFix: _state does still not provide the near_plane in picking mode!!!
548// std::cerr << "radius in picking: " << r*l << std::endl;
549 }
550}
551
552
553//----------------------------------------------------------------------------
554
555
556template <class PolyLine>
557void
558PolyLineNodeT<PolyLine>::
559pick_edges( GLState& _state, unsigned int _offset)
560{
561 // Check if we have any edges to draw ( % 0 causes division by zero on windows)
562 if ( polyline_.n_edges() == 0 )
563 return;
564
565 glDepthRange(0.0, 0.999999);
566
567 static ShaderGenDesc desc;
569 {
570 desc.vertexTemplateFile = "Picking/vertex.glsl";
571 desc.fragmentTemplateFile = "Picking/pick_vertices_fs2.glsl";
572 }
573 else
574 {
575 desc.vertexTemplateFile = "Picking/pick_vertices_vs.glsl";
576 desc.fragmentTemplateFile = "Picking/pick_vertices_fs.glsl";
577 }
578 GLSL::Program* pickShader = ACG::ShaderCache::getInstance()->getProgram(&desc, nullptr);
579
580 if (pickShader && pickShader->isLinked())
581 {
582 // Update the vbo only if required.
583 if (updateVBO_)
584 updateVBO();
585
586 // Bind the vertex array
587 vbo_.bind();
588
589 int pickOffsetIndex = int(_state.pick_current_index());
590
591 vertexDecl_.activateShaderPipeline(pickShader);
592
593 pickShader->use();
594
595 ACG::GLMatrixf transform = _state.projection() * _state.modelview();
596
597 pickShader->setUniform("mWVP", transform);
598 pickShader->setUniform("pickVertexOffset", pickOffsetIndex);
599
600 int numIndices = polyline_.n_vertices() + (polyline_.is_closed() ? 1 : 0);
601 glDrawArrays(GL_LINE_STRIP, 0, numIndices);
602
603 vertexDecl_.deactivateShaderPipeline(pickShader);
604 pickShader->disable();
605
606 vbo_.unbind();
607 }
608 else
609 {
610 // save old values
611 float line_width_old = _state.line_width();
612 // _state.set_line_width(2*line_width_old);
613 _state.set_line_width(14);
614
615 unsigned int n_end = polyline_.n_edges() + 1;
616 if (!polyline_.is_closed()) --n_end;
617
618 for (unsigned int i = 0; i < n_end; ++i) {
619 _state.pick_set_name(i + _offset);
620 glBegin(GL_LINES);
621 glArrayElement(i % polyline_.n_vertices());
622 glArrayElement((i + 1) % polyline_.n_vertices());
623 glEnd();
624 }
625
626 _state.set_line_width(line_width_old);
627 }
628
629 glDepthRange(0.0, 1.0);
630
631}
632
633//----------------------------------------------------------------------------
634
635template <class PolyLine>
636void
638setupVertexDeclaration(VertexDeclaration* _dst, int _colorSource) const {
639 // Update the vertex declaration based on the input data:
640 _dst->clear();
641
642
643 // We always output vertex positions
644 _dst->addElement(GL_FLOAT, 3, ACG::VERTEX_USAGE_POSITION);
645
646 // current byte offset
647 size_t curOffset = 12;
648
649 // Use the normals if available
650 if (polyline_.vertex_normals_available())
651 {
652 _dst->addElement(GL_FLOAT, 3, ACG::VERTEX_USAGE_NORMAL, curOffset);
653 curOffset += 12;
654 }
655
656 // colors
657 if (polyline_.vertex_colors_available())
658 {
659 if (_colorSource == 1)
660 _dst->addElement(GL_UNSIGNED_BYTE, 4, ACG::VERTEX_USAGE_COLOR, curOffset);
661 curOffset += 4;
662 }
663
664 if (polyline_.edge_colors_available())
665 {
666 if (_colorSource == 2)
667 _dst->addElement(GL_UNSIGNED_BYTE, 4, ACG::VERTEX_USAGE_COLOR, curOffset);
668 curOffset += 4;
669 }
670
671
672 // Add custom vertex elements to declaration
673 for (size_t i = 0; i < customBuffers_.size(); ++i) {
674 ACG::VertexElement tmp = customBuffers_[i].first;
675 tmp.pointer_ = 0;
677 tmp.setByteOffset(curOffset);
678 _dst->addElement(&tmp);
679
680 curOffset += VertexDeclaration::getElementSize(&tmp);
681 }
682
683 _dst->setVertexStride(curOffset);
684}
685
686//----------------------------------------------------------------------------
687
688template <class PolyLine>
689size_t
691fillVertexBuffer(void *_buf, size_t _bufSize, bool _addLineStripEndVertex) {
692
693 // register custom properties defined in polyline
694
695 for (unsigned int i = 0; i < polyline_.get_num_custom_properties(); ++i) {
696
697 typename PolyLine::CustomPropertyHandle proph = polyline_.enumerate_custom_property_handles(i);
698
699
700
701 const void* propDataBuf = polyline_.get_custom_property_buffer(proph);
702
703 typename std::map< typename PolyLine::CustomPropertyHandle, int >::iterator mapEntry = polylinePropMap_.find(proph);
704
705 // insert newly defined properties
706 if (mapEntry == polylinePropMap_.end()) {
707
708 // setup element description
710
711 unsigned int propSize = 0;
712 if (polyline_.get_custom_property_shader_binding(proph, &propSize, &desc.shaderInputName_, &desc.type_)) {
713 // assume aligned memory without byte padding
715 desc.pointer_ = 0;
716
717 polylinePropMap_[proph] = addCustomBuffer(desc, propDataBuf);
718 }
719 }
720 else // otherwise update pointer of property data buffer
721 setCustomBuffer(mapEntry->second, propDataBuf);
722 }
723
724
725 // Update vertex declarations
726 setupVertexDeclaration(&vertexDecl_, 0);
727 setupVertexDeclaration(&vertexDeclVCol_, 1);
728 setupVertexDeclaration(&vertexDeclECol_, 2);
729
730
731 // fill buffer
732
733 const unsigned int stride = vertexDecl_.getVertexStride();
734
735 char* data = static_cast<char*>(_buf);
736 size_t bytesWritten = 0;
737
738 for (unsigned int i = 0 ; i < polyline_.n_vertices() && bytesWritten + stride <= _bufSize; ++i) {
739 writeVertex(i, data + i * stride);
740 bytesWritten += stride;
741 }
742
743 if (_addLineStripEndVertex && bytesWritten + stride <= _bufSize) {
744 // First point is added to the end for a closed loop
745 writeVertex(0, data + polyline_.n_vertices() * stride);
746 bytesWritten += stride;
747 }
748
749 return bytesWritten;
750}
751
752//----------------------------------------------------------------------------
753
754template <class PolyLine>
755void
757updateVBO() {
758
759 setupVertexDeclaration(&vertexDecl_, 0);
760
761 const unsigned int stride = vertexDecl_.getVertexStride();
762
763 // size in bytes of vbo, create additional vertex for closed loop indexing
764 size_t bufferSize = stride * (polyline_.n_vertices() + 1);
765
766 // Create the required array
767 std::vector<char> vboData(bufferSize);
768
769 if (bufferSize > 0) {
770 size_t bytesWritten = fillVertexBuffer(&vboData[0], bufferSize, true);
771
772 if (bytesWritten != bufferSize)
773 std::cerr << "PolyLineNode: fill vertex buffer only wrote " << bytesWritten << " bytes instead of expected " << bufferSize << " bytes" << std::endl;
774
775 // Move data to the buffer in gpu memory
776 vbo_.upload(bufferSize, &vboData[0], GL_STATIC_DRAW);
777 vbo_.unbind();
778 }
779
780 // Index buffer for selected vertices
781 selectedVertexIndexBuffer_.clear();
782
783 // Index buffer for selected vertices
784 selectedEdgeIndexBuffer_.clear();
785
786 for (unsigned int i = 0 ; i < polyline_.n_vertices(); ++i) {
787
788 // Create an ibo in system memory for vertex selection
789 if ( polyline_.vertex_selections_available() && polyline_.vertex_selected(i) )
790 selectedVertexIndexBuffer_.push_back(i);
791
792 // Create an ibo in system memory for edge selection
793 if ( polyline_.edge_selections_available() && polyline_.edge_selected(i) ) {
794 selectedEdgeIndexBuffer_.push_back(i);
795 selectedEdgeIndexBuffer_.push_back( (i + 1) % polyline_.n_vertices() );
796 }
797
798 }
799
800 // Update done.
801 updateVBO_ = false;
802}
803
804//----------------------------------------------------------------------------
805
806template <class PolyLine>
807void
809writeVertexColor(unsigned int _vertex, bool _colorSourceVertex, void* _dst) const
810{
811 const VertexDeclaration* declToUse = _colorSourceVertex ? &vertexDeclVCol_ : &vertexDeclECol_;
812
813 unsigned int byteOffset = declToUse->findElementByUsage(VERTEX_USAGE_COLOR)->getByteOffset();
814 unsigned char* ucdata = ((unsigned char*)_dst) + byteOffset;
815
816 Point col;
817 if (_colorSourceVertex)
818 col = polyline_.vertex_color(_vertex); // per vertex
819 else
820 {
821 // edge colors
822 // use the 2nd vertex of each edge as the provoking vertex
823 int edgeID = (_vertex + polyline_.n_edges() - 1) % polyline_.n_edges();
824 col = polyline_.edge_color(edgeID);
825 }
826
827 // rgb
828 for (int i = 0; i < 3; ++i)
829 {
830 // convert to normalized ubyte
831 int ival = int(col[i] * 255.0);
832 ival = std::min(std::max(ival, 0), 255);
833 ucdata[i] = ival;
834 }
835 ucdata[3] = 0xff; // alpha
836}
837
838//----------------------------------------------------------------------------
839
840template <class PolyLine>
841void
843writeVertex(unsigned int _vertex, void* _dst) {
844
845 // position and normal in float
846 float* fdata = (float*)_dst;
847
848 // Copy from internal storage to VBO in CPU memory
849 for ( unsigned int j = 0 ; j < 3 ; ++j)
850 *(fdata++) = polyline_.point(_vertex)[j];
851
852 // Also write normal into buffer if available
853 if ( polyline_.vertex_normals_available() )
854 for ( unsigned int j = 0 ; j < 3 ; ++j)
855 *(fdata++) = polyline_.vertex_normal(_vertex)[j];
856
857 if (polyline_.vertex_colors_available())
858 writeVertexColor(_vertex, true, _dst);
859
860 if (polyline_.edge_colors_available())
861 writeVertexColor(_vertex, false, _dst);
862
863 int customElementOffset = vertexDeclVCol_.findElementIdByUsage(VERTEX_USAGE_SHADER_INPUT);
864
865 if (customElementOffset >= 0)
866 {
867 // copy custom data byte-wise
868 for (unsigned int i = 0; i < customBuffers_.size(); ++i) {
869
870 // element in custom input buffer
871 const ACG::VertexElement* veInput = &customBuffers_[i].first;
872 unsigned int elementInputStride = veInput->getByteOffset();
873 unsigned int elementSize = ACG::VertexDeclaration::getElementSize(veInput);
874
875 if (!elementInputStride)
876 elementInputStride = elementSize;
877
878 // element in vertex buffer
879 const ACG::VertexElement* ve = vertexDeclVCol_.getElement(i + static_cast<unsigned int>(customElementOffset));
880
881 const char* src = (const char*)customBuffers_[i].second;
882
883 memcpy((char*)_dst + ve->getByteOffset(), src + elementInputStride * _vertex, elementSize);
884 }
885 }
886}
887
888//----------------------------------------------------------------------------
889
890template <class PolyLine>
891void
894
895 // Block if we do not have any vertices
896 if ( polyline_.n_vertices() == 0 )
897 return;
898
899 // init base render object
901
902 if (compatibilityProfile( ) ) {
903 _state.enable(GL_COLOR_MATERIAL);
904 _state.enable(GL_LIGHTING);
905 }
906 ro.initFromState(&_state);
907
908 ro.setMaterial(_mat);
909
910 // draw after scene-meshes
911 ro.priority = 1;
912
913 // Update the vbo only if required.
914 if ( updateVBO_ )
915 updateVBO();
916
917 // Set to the right vbo
918 ro.vertexBuffer = vbo_.id();
919
920 // Set style
921 ro.debugName = "PolyLine";
922 ro.blending = false;
923 ro.depthTest = true;
924
925 // Default color
926 ACG::Vec4f defaultColor = _state.ambient_color() + _state.diffuse_color();
927 ACG::Vec4f selectionColor = ACG::Vec4f(1.0,0.0,0.0,1.0);
928
929 // Viewport size
930 ACG::Vec2f screenSize(float(_state.viewport_width()), float(_state.viewport_height()));
931
932 for (unsigned int i = 0; i < _drawMode.getNumLayers(); ++i) {
933 ACG::SceneGraph::Material localMaterial = *_mat;
934
936
938 ro.shaderDesc.shadeMode = SG_SHADE_UNLIT;
939 ro.vertexDecl = &vertexDecl_;
940
941 //---------------------------------------------------
942 // No lighting!
943 // Therefore we need some emissive color
944 //---------------------------------------------------
945 localMaterial.baseColor(defaultColor);
946 ro.setMaterial(&localMaterial);
947
948
949 switch (props->primitive()) {
950
951 case ACG::SceneGraph::DrawModes::PRIMITIVE_POINT:
952
953 // Render all vertices which are selected via an index buffer
954 ro.debugName = "polyline.Points.selected";
955 localMaterial.baseColor(selectionColor);
956 ro.setMaterial(&localMaterial);
957
958 // Point Size geometry shader
959 ro.setupPointRendering(_mat->pointSize(), screenSize);
960
961 // selection without colors
962 ro.shaderDesc.vertexColors = false;
963
964 if (!selectedVertexIndexBuffer_.empty())
965 {
966 ro.glDrawElements(GL_POINTS, selectedVertexIndexBuffer_.size(), GL_UNSIGNED_INT, &(selectedVertexIndexBuffer_[0]));
967 // apply user settings
968 applyRenderObjectSettings(props->primitive(), &ro);
969
970 _renderer->addRenderObject(&ro);
971 }
972
973 // Render all vertices (ignore selection here!)
974 ro.debugName = "polyline.Points";
975 localMaterial.baseColor(defaultColor);
976 ro.setMaterial(&localMaterial);
977 ro.glDrawArrays(GL_POINTS, 0, polyline_.n_vertices());
978
979 if (props->colored() && polyline_.vertex_colors_available())
980 {
981 ro.vertexDecl = &vertexDeclVCol_;
982 ro.shaderDesc.vertexColors = true;
983 }
984
985
986 // Point Size geometry shader
987 ro.setupPointRendering(_mat->pointSize(), screenSize);
988
989 // apply user settings
990 applyRenderObjectSettings(props->primitive(), &ro);
991
992 _renderer->addRenderObject(&ro);
993
994 break;
995
996 case ACG::SceneGraph::DrawModes::PRIMITIVE_WIREFRAME:
997 case ACG::SceneGraph::DrawModes::PRIMITIVE_EDGE:
998
999 // Render all edges which are selected via an index buffer
1000 ro.debugName = "polyline.Wireframe.selected";
1001 localMaterial.baseColor(selectionColor);
1002 ro.setMaterial(&localMaterial);
1003
1004 // Line Width geometry shader
1005 ro.setupLineRendering(_state.line_width(), screenSize);
1006
1007 // selection without colors
1008 ro.shaderDesc.vertexColors = false;
1009
1010 if (!selectedEdgeIndexBuffer_.empty())
1011 {
1012 ro.glDrawElements(GL_LINES, selectedEdgeIndexBuffer_.size(), GL_UNSIGNED_INT, &(selectedEdgeIndexBuffer_[0]));
1013
1014 // apply user settings
1015 applyRenderObjectSettings(props->primitive(), &ro);
1016
1017 _renderer->addRenderObject(&ro);
1018 }
1019
1020 ro.debugName = "polyline.Wireframe";
1021 localMaterial.baseColor(defaultColor);
1022 ro.setMaterial(&localMaterial);
1023 // The first point is mapped to an additional last point in buffer, so we can
1024 // just Render one point more to get a closed line
1025 if ( polyline_.is_closed() )
1026 ro.glDrawArrays(GL_LINE_STRIP, 0, polyline_.n_vertices() + 1);
1027 else
1028 ro.glDrawArrays(GL_LINE_STRIP, 0, polyline_.n_vertices());
1029
1030 if (props->colored() && polyline_.edge_colors_available())
1031 {
1032 ro.vertexDecl = &vertexDeclECol_;
1033 ro.shaderDesc.vertexColors = true;
1034 }
1035
1036 // Line Width geometry shader
1037 ro.setupLineRendering(_state.line_width(), screenSize);
1038
1039 // apply user settings
1040 applyRenderObjectSettings(props->primitive(), &ro);
1041
1042 _renderer->addRenderObject(&ro);
1043
1044 break;
1045
1046
1047 case ACG::SceneGraph::DrawModes::PRIMITIVE_POLYGON:
1048 {
1049 // create sphere object for each vertex
1050 // potential optimization: create only one render object and use instancing
1051
1052 // use world space radius or screen space point size?
1053 bool screenScale = _drawMode & POINTS_SPHERES_SCREEN;
1054
1055 // clear shaders used by thick line / point drawing
1056 ro.shaderDesc.vertexTemplateFile.clear();
1057 ro.shaderDesc.geometryTemplateFile.clear();
1058 ro.shaderDesc.fragmentTemplateFile.clear();
1059
1060 // create sphere if not yet done
1061 if (!sphere_)
1062 sphere_ = new GLSphere(10, 10);
1063
1064 // precompute desired radius of projected sphere
1065 double r = 1.0;
1066 if (screenScale)
1067 r = 0.5*_state.point_size() / double(_state.viewport_height())*2.0*tan(0.5*_state.fovy());
1068
1069 // get eye position and view direction in world space
1070 Vec3d eyePos = _state.eye();
1071 Vec3d viewDir = _state.viewing_direction();
1072
1073 // render-objects for the selected points with selection color
1074 if (polyline_.vertex_selections_available())
1075 {
1076 ro.debugName = "polyline.Sphere.selected";
1077 localMaterial.baseColor(selectionColor);
1078 ro.setMaterial(&localMaterial);
1079
1080 for (unsigned int i = 0; i < polyline_.n_vertices(); ++i)
1081 {
1082 if (polyline_.vertex_selected(i))
1083 {
1084 double radius = _state.point_size();
1085 if (screenScale)
1086 {
1087 // compute radius in 3D
1088 const Vec3d p = (Vec3d)polyline_.point(i) - eyePos;
1089 radius = (p | viewDir) * r;
1090 }
1091
1092 sphere_->addToRenderer(_renderer, &ro, radius, (Vec3f)polyline_.point(i));
1093 }
1094 }
1095 }
1096
1097 // unselected points with default color
1098 ro.debugName = "polyline.Sphere";
1099 localMaterial.baseColor(defaultColor);
1100 ro.setMaterial(&localMaterial);
1101
1102 for (unsigned int i = 0; i < polyline_.n_vertices(); ++i)
1103 {
1104 if (!polyline_.vertex_selections_available() || !polyline_.vertex_selected(i))
1105 {
1106 double radius = _state.point_size();
1107 if (screenScale)
1108 {
1109 // compute radius in 3D
1110 const Vec3d p = (Vec3d)polyline_.point(i) - eyePos;
1111 radius = (p | viewDir) * r;
1112 }
1113
1114 sphere_->addToRenderer(_renderer, &ro, radius, (Vec3f)polyline_.point(i));
1115 }
1116 }
1117 } break;
1118
1119
1120 default:
1121 break;
1122 }
1123
1124 }
1125
1126}
1127
1128//----------------------------------------------------------------------------
1129
1130template <class PolyLine>
1131int
1133addCustomBuffer( const ACG::VertexElement& _desc, const void* _buffer) {
1134
1135 if (_buffer) {
1136 customBuffers_.push_back( std::pair<ACG::VertexElement, const void*>(_desc, _buffer) );
1137 update();
1138
1139 return int(customBuffers_.size()-1);
1140 }
1141 else
1142 {
1143 std::cerr << "PolyLineNodeT::addCustomBuffer - null pointer buffer" << std::endl;
1144 return -1;
1145 }
1146}
1147
1148//----------------------------------------------------------------------------
1149
1150template <class PolyLine>
1151void
1153setCustomBuffer( int _id, const void* _buffer) {
1154
1155 customBuffers_[_id].second = _buffer;
1156 update();
1157}
1158
1159//=============================================================================
1160} // namespace SceneGraph
1161} // namespace ACG
1162//=============================================================================
static void disableClientState(GLenum _cap)
replaces glDisableClientState, supports locking
Definition GLState.cc:1584
Vec3d eye() const
get eye point
Definition GLState.cc:886
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
const GLMatrixd & modelview() const
get modelview matrix
Definition GLState.hh:816
static void enableClientState(GLenum _cap)
replaces glEnableClientState, supports locking
Definition GLState.cc:1570
int viewport_width() const
get viewport width
Definition GLState.hh:847
void pick_set_name(size_t _idx)
sets the current name/color (like glLoadName(_idx))
Definition GLState.cc:1061
Vec3d viewing_direction() const
get viewing ray
Definition GLState.hh:873
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
void set_color(const Vec4f &_col)
set color
Definition GLState.cc:691
static void disable(GLenum _cap, bool _warnRemoved=true)
replaces glDisable, but supports locking
Definition GLState.cc:1527
void set_line_width(float _f)
set line width
Definition GLState.cc:791
const Vec4f & ambient_color() const
get ambient color
Definition GLState.hh:956
void set_point_size(float _f)
set point size
Definition GLState.cc:776
double fovy() const
get field of view in y direction
Definition GLState.cc:868
size_t pick_current_index() const
Returns the current color picking index (can be used for caching)
Definition GLState.cc:1131
int viewport_height() const
get viewport height
Definition GLState.hh:849
float line_width() const
get line width
Definition GLState.hh:1000
const Vec4f & diffuse_color() const
get diffuse color
Definition GLState.hh:961
static void bindBuffer(GLenum _target, GLuint _buffer)
replaces glBindBuffer, supports locking
Definition GLState.cc:1820
float point_size() const
get point size
Definition GLState.hh:995
virtual void addRenderObject(RenderObject *_renderObject)
Callback for the scenegraph nodes, which send new render objects via this function.
Definition IRenderer.cc:104
DrawModes::DrawMode drawMode() const
Return the own draw modes of this node.
Definition BaseNode.hh:430
DrawModeProperties stores a set of properties that defines, how to render an object.
Definition DrawModes.hh:177
const DrawModeProperties * getLayer(unsigned int _i) const
returns the property set at layer i
Definition DrawModes.cc:525
size_t getNumLayers() const
returns the layer count
Definition DrawModes.cc:521
void baseColor(const Vec4f &_c)
set the base color (Sets the baseColor which is the same as the emission(const Vec4f& _c) )
void pointSize(float _sz)
set point size (default: 1.0)
void getRenderObjects(ACG::IRenderer *_renderer, ACG::GLState &_state, const ACG::SceneGraph::DrawModes::DrawMode &_drawMode, const ACG::SceneGraph::Material *_mat) override
Add the objects to the given renderer.
DrawModes::DrawMode POINTS_SPHERES
This defines a local point spheres draw mode for all polyLine nodes.
void updateVBO()
Trigger an update of the vbo.
void writeVertexColor(unsigned int _vertex, bool _colorSourceVertex, void *_dst) const
Write color for rendering to a buffer.
void boundingBox(Vec3d &_bbMin, Vec3d &_bbMax) override
update bounding box
void setCustomBuffer(int _id, const void *_buffer)
void setupVertexDeclaration(VertexDeclaration *_dst, int _colorSource) const
Create the vertex declaration.
int addCustomBuffer(const ACG::VertexElement &_desc, const void *_buffer)
void draw(GLState &, const DrawModes::DrawMode &_drawMode) override
draw lines and normals
PolyLineNodeT(PolyLine &_pl, BaseNode *_parent=0, std::string _name="<PolyLineNode>")
Constructor.
size_t fillVertexBuffer(void *_buf, size_t _bufSize, bool _addLineStripEndVertex)
Fill a buffer with vertex data.
void writeVertex(unsigned int _vertex, void *_dst)
Write vertex data for rendering to a buffer.
DrawModes::DrawMode availableDrawModes() const override
return available draw modes
DrawModes::DrawMode POINTS_SPHERES_SCREEN
This defines a local point spheres draw mode for all polyLine nodes with constant screen size.
void pick(GLState &_state, PickTarget _target) override
picking
static ShaderCache * getInstance()
Return instance of the ShaderCache singleton.
GLSL::Program * getProgram(const ShaderGenDesc *_desc, const std::vector< unsigned int > &_mods)
Query a dynamically generated program from cache.
Class to define the vertex input layout.
void addElement(const VertexElement *_pElement)
static size_t getGLTypeSize(unsigned int _type)
void setVertexStride(unsigned int _stride)
static size_t getElementSize(const VertexElement *_pElement)
const VertexElement * findElementByUsage(VERTEX_USAGE _usage) const
GLSL program class.
bool isLinked()
Returns if the program object has been succesfully linked.
void disable()
Resets to standard rendering pipeline.
void use()
Enables the program object for using.
void setUniform(const char *_name, GLint _value)
Set int uniform to specified value.
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
DrawMode POINTS_COLORED
draw colored, but not lighted points (requires point colors)
Definition DrawModes.cc:74
DrawMode WIREFRAME
draw wireframe
Definition DrawModes.cc:78
DrawMode POINTS
draw unlighted points using the default base color
Definition DrawModes.cc:73
DrawMode EDGES_COLORED
draw edges with colors (without shading)
Definition DrawModes.cc:77
const DrawMode & addDrawMode(const std::string &_name, bool _propertyBased)
Add a custom DrawMode.
Definition DrawModes.cc:755
PickTarget
What target to use for picking.
Definition PickTarget.hh:74
@ PICK_EDGE
picks edges (may not be implemented for all nodes)
Definition PickTarget.hh:80
@ 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, 4 > Vec4f
Definition VectorT.hh:138
bool ACGDLLEXPORT openGLVersionTest(const int _major, const int _minor)
Definition gl.hh:275
@ VERTEX_USAGE_NORMAL
"inNormal"
@ VERTEX_USAGE_COLOR
"inColor"
@ VERTEX_USAGE_POSITION
"inPosition"
@ VERTEX_USAGE_SHADER_INPUT
defined by user via VertexElement::shaderInputName_
bool compatibilityProfile()
get opengl core profile setting
Definition gl.cc:171
VectorT< double, 3 > Vec3d
Definition VectorT.hh:121
Interface class between scenegraph and renderer.
ShaderGenDesc shaderDesc
Drawmode and other shader params.
void setupLineRendering(float _lineWidth, const Vec2f &_screenSize)
Setup rendering of thick lines.
const VertexDeclaration * vertexDecl
Defines the vertex buffer layout, ignored if VAO is provided.
void setupShaderGenFromDrawmode(const SceneGraph::DrawModes::DrawModeProperties *_props)
Fills out ShaderGenDesc parameters based on Drawmode properties.
int priority
Priority to allow sorting of objects.
GLuint vertexBuffer
VBO, IBO ids, ignored if VAO is provided.
void initFromState(GLState *_glState)
Initializes a RenderObject instance.
void setupPointRendering(float _pointSize, const Vec2f &_screenSize)
Setup rendering of circle points.
Description of one vertex element.
void setByteOffset(unsigned int _offset)
unsigned int numElements_
how many elements of type_
const void * pointer_
Offset in bytes to the first occurrence of this element in vertex buffer; Or address to vertex data i...
VERTEX_USAGE usage_
position, normal, shader input ..
unsigned int getByteOffset() const
unsigned int type_
GL_FLOAT, GL_UNSIGNED_BYTE, GL_INT, ...
const char * shaderInputName_
set shader input name, if usage_ = VERTEX_USAGE_USER_DEFINED otherwise this is set automatically,...