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