Developer Documentation
BSplineSurfaceNodeT.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 * $LastChangedBy$ *
46 * $Date$ *
47 * *
48 \*===========================================================================*/
49 
50 
51 //=============================================================================
52 //
53 // CLASS BSplineSurfaceNodeT - IMPLEMENTATION
54 // Author: Ellen Dekkers <dekkers@cs.rwth-aachen.de>
55 //
56 //=============================================================================
57 
58 #define ACG_BSPLINESURFACENODET_C
59 
60 //== INCLUDES =================================================================
61 
62 #include "BSplineSurfaceNodeT.hh"
63 #include <ACG/GL/gl.hh>
64 #include <ACG/GL/GLError.hh>
65 #include <ACG/GL/IRenderer.hh>
66 #include <ACG/Utils/VSToolsT.hh>
67 #include <vector>
68 
69 
70 
71 //== NAMESPACES ===============================================================
72 
73 namespace ACG {
74 namespace SceneGraph {
75 
76 //== IMPLEMENTATION ==========================================================
77 
78 
79 template <class BSplineSurfaceType>
80 void
82 boundingBox(Vec3d& _bbMin, Vec3d& _bbMax)
83 {
84  for (unsigned int i = 0; i < bsplineSurface_.n_control_points_m(); ++i)
85  {
86  for (unsigned int j = 0; j < bsplineSurface_.n_control_points_n(); ++j)
87  {
88  _bbMin.minimize(bsplineSurface_(i,j));
89  _bbMax.maximize(bsplineSurface_(i,j));
90  }
91  }
92 }
93 
94 //----------------------------------------------------------------------------
95 
96 template <class BSplineSurfaceType>
100 {
101  DrawModes::DrawMode drawModes(0);
102 
103  drawModes |= DrawModes::POINTS;
104  drawModes |= DrawModes::WIREFRAME;
105  drawModes |= DrawModes::HIDDENLINE;
106  drawModes |= DrawModes::SOLID_SMOOTH_SHADED;
107  drawModes |= DrawModes::SOLID_FLAT_SHADED;
108  drawModes |= DrawModes::SOLID_PHONG_SHADED;
109  drawModes |= DrawModes::SOLID_SHADER;
110  drawModes |= DrawModes::SOLID_TEXTURED;
111  drawModes |= DrawModes::SOLID_1DTEXTURED;
112 
113  return drawModes;
114 }
115 
116 
117 //----------------------------------------------------------------------------
118 
119 template <class BSplineSurfaceType>
120 void
122 getRenderObjects(IRenderer* _renderer, GLState& _state, const DrawModes::DrawMode& _drawMode, const Material* _mat)
123 {
124  // check if textures are still valid
125  if ( bspline_selection_draw_mode_ == CONTROLPOINT
126  && controlPointSelectionTexture_valid_ == false)
127  updateControlPointSelectionTexture(_state);
128  if ( bspline_selection_draw_mode_ == KNOTVECTOR
129  && knotVectorSelectionTexture_valid_ == false)
130  updateKnotVectorSelectionTexture(_state);
131 
132 
133  for (size_t i = 0; i < _drawMode.getNumLayers(); ++i)
134  {
135  const DrawModes::DrawModeProperties* props = _drawMode.getLayer(i);
136 
137 
138  RenderObject ro;
139  ro.initFromState(&_state);
140  ro.setupShaderGenFromDrawmode(props);
141  ro.depthTest = true;
142 
143  // generated texcoords for environment mapping should be computed in fragment shader,
144  // because normals aren't available in the vertex shader
145  ro.shaderDesc.texGenPerFragment = true;
146 
147  if ( props->textured() && arb_texture_idx_)
148  ro.addTexture(ACG::RenderObject::Texture(arb_texture_idx_), 0);
149 
150  if (props->primitive() == DrawModes::PRIMITIVE_POLYGON || props->primitive() == DrawModes::PRIMITIVE_WIREFRAME)
151  {
152  updateSurfaceMesh();
153 
154  ro.vertexBuffer = surfaceVBO_.id();
155  ro.indexBuffer = surfaceIBO_.id();
156  ro.vertexDecl = &surfaceDecl_;
157 
158  if (props->primitive() == DrawModes::PRIMITIVE_WIREFRAME)
159  ro.fillMode = GL_LINE;
160  else
161  ro.fillMode = GL_FILL;
162 
163  GLenum roPrimitives = GL_TRIANGLES;
164 
165 #ifdef GL_ARB_tessellation_shader
166  bool tessellationMode = ACG::openGLVersion(4, 0) && Texture::supportsTextureBuffer();
167 
168  if (tessellationMode)
169  {
170  // dynamic lod tessellation and spline evaluation on gpu
171 
172  if (!controlPointTex_.is_valid())
173  updateTexBuffers();
174 
175  ro.shaderDesc.tessControlTemplateFile = "BSpline/tesscontrol_lod.glsl";
176  ro.shaderDesc.tessEvaluationTemplateFile = "BSpline/tesseval_lod.glsl";
177 
178 
179  QString shaderMacro;
180 
181  shaderMacro.sprintf("#define BSPLINE_DEGREE_U %i", bsplineSurface_.degree_m());
182  ro.shaderDesc.macros.push_back(shaderMacro);
183 
184  shaderMacro.sprintf("#define BSPLINE_DEGREE_V %i", bsplineSurface_.degree_n());
185  ro.shaderDesc.macros.push_back(shaderMacro);
186 
187  shaderMacro.sprintf("#define BSPLINE_KNOTVEC_U %i", bsplineSurface_.degree_m() * 2 + 1);
188  ro.shaderDesc.macros.push_back(shaderMacro);
189 
190  shaderMacro.sprintf("#define BSPLINE_KNOTVEC_V %i", bsplineSurface_.degree_n() * 2 + 1);
191  ro.shaderDesc.macros.push_back(shaderMacro);
192 
193 
194  ro.setUniform("controlPointTex", int(1));
195  ro.setUniform("knotBufferU", int(2));
196  ro.setUniform("knotBufferV", int(3));
197 
198  ro.setUniform("uvRange", Vec4f(bsplineSurface_.loweru(), bsplineSurface_.upperu(),
199  bsplineSurface_.lowerv(), bsplineSurface_.upperv()));
200 
201  ro.addTexture(RenderObject::Texture(controlPointTex_.id(), GL_TEXTURE_2D), 1, false);
202  ro.addTexture(RenderObject::Texture(knotTexBufferU_.id(), GL_TEXTURE_BUFFER), 2, false);
203  ro.addTexture(RenderObject::Texture(knotTexBufferV_.id(), GL_TEXTURE_BUFFER), 3, false);
204 
205  roPrimitives = GL_PATCHES;
206  }
207 
208  if (tessellationMode)
209  ro.patchVertices = 3;
210 #endif
211 
212  ro.glDrawElements(roPrimitives, surfaceIndexCount_, GL_UNSIGNED_INT, 0);
213 
214  _renderer->addRenderObject(&ro);
215 
216  }
217  }
218 
219  // draw the control net (includes selection on the net)
220  if (render_control_net_)
221  {
222  // update if necessary
223  updateControlNetMesh();
224  updateControlNetMeshSel();
225 
226  // setup base renderobject for unlit point and line rendering
227  RenderObject ro;
228  ro.initFromState(&_state);
229  ro.depthTest = true;
230  ro.shaderDesc.shadeMode = SG_SHADE_UNLIT;
231 
232  ro.vertexBuffer = controlNetVBO_.id();
233  ro.vertexDecl = &controlNetDecl_;
234 
235  Vec2f screenSize = Vec2f(_state.viewport_width(), _state.viewport_height());
236 
237  // selected control points
238  if (controlNetSelIndices_)
239  {
240  ro.name = "BSplineSurface_ControlPointSel";
241 
242  ro.setupPointRendering(10.0f, screenSize);
243 
244  Vec4f selColor = generateHighlightColor(controlnet_color_);
245  ro.emissive = Vec3f(selColor[0], selColor[1], selColor[2]);
246 
247  ro.indexBuffer = controlNetSelIBO_.id();
248 
249  ro.glDrawElements(GL_POINTS, controlNetSelIndices_, GL_UNSIGNED_INT, 0);
250 
251  _renderer->addRenderObject(&ro);
252  }
253 
254  // all control points
255  {
256  ro.name = "BSplineSurface_ControlPoint";
257  ro.setupPointRendering(_state.point_size() + 4.0f, screenSize);
258 
259  ro.emissive = Vec3f(controlnet_color_[0], controlnet_color_[1], controlnet_color_[2]);
260 
261  GLsizei numPoints = bsplineSurface_.n_control_points_m() * bsplineSurface_.n_control_points_n();
262  ro.glDrawArrays(GL_POINTS, 0, numPoints);
263 
264  _renderer->addRenderObject(&ro);
265  }
266 
267  ro.resetPointRendering();
268 
269  // all line segments
270  {
271  ro.name = "BSplineSurface_ControlNetLines";
272  ro.setupLineRendering(_state.line_width() + 2.0f, screenSize);
273 
274  ro.indexBuffer = controlNetLineIBO_.id();
275 
276  ro.glDrawElements(GL_LINES, controlNetLineIndices_, GL_UNSIGNED_INT, 0);
277 
278  _renderer->addRenderObject(&ro);
279  }
280  }
281 }
282 
283 
284 //----------------------------------------------------------------------------
285 
286 template <class BSplineSurfaceType>
287 void
289 draw(GLState& _state, const DrawModes::DrawMode& _drawMode)
290 {
291  GLenum prev_depth = _state.depthFunc();
292 
293  glPushAttrib(GL_ENABLE_BIT);
294 
295  // check if textures are still valid
296  if ( bspline_selection_draw_mode_ == CONTROLPOINT
297  && controlPointSelectionTexture_valid_ == false)
298  updateControlPointSelectionTexture(_state);
299  if ( bspline_selection_draw_mode_ == KNOTVECTOR
300  && knotVectorSelectionTexture_valid_ == false)
301  updateKnotVectorSelectionTexture(_state);
302 
303 
304  if (_drawMode & DrawModes::POINTS)
305  {
306  ACG::GLState::disable(GL_LIGHTING);
307  ACG::GLState::shadeModel(GL_FLAT);
308  render( _state, false);
309  }
310 
311  if (_drawMode & DrawModes::WIREFRAME)
312  {
313  glPushAttrib(GL_ENABLE_BIT);
314 
315  ACG::GLState::disable( GL_CULL_FACE );
316  ACG::GLState::disable(GL_LIGHTING);
317  ACG::GLState::shadeModel(GL_FLAT);
318  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
319 
320  render( _state, false);
321 
322  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
323  glPopAttrib();
324  }
325 
326 
327  if (_drawMode & DrawModes::HIDDENLINE)
328  {
329  Vec4f clear_color = _state.clear_color();
330  Vec4f base_color = _state.base_color();
331  clear_color[3] = 1.0;
332 
333  ACG::GLState::enable(GL_DEPTH_TEST);
334  ACG::GLState::disable(GL_LIGHTING);
335  ACG::GLState::shadeModel(GL_FLAT);
336  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
337  _state.set_base_color(clear_color);
338 
339  ACG::GLState::depthRange(0.01, 1.0);
340 
341  render( _state, true);
342 
343  ACG::GLState::depthRange(0.0, 1.0);
344 
345  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
346  ACG::GLState::depthFunc(GL_LEQUAL);
347  _state.set_base_color(base_color);
348 
349  render( _state, false);
350 
351  ACG::GLState::depthFunc(prev_depth);
352  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
353  }
354 
355 
356  if ( ( _drawMode & DrawModes::SOLID_FLAT_SHADED ))
357  {
358  ACG::GLState::enable(GL_LIGHTING);
359  ACG::GLState::shadeModel(GL_FLAT);
360 
361  ACG::GLState::enable(GL_AUTO_NORMAL);
362  ACG::GLState::enable(GL_NORMALIZE);
363 
364  ACG::GLState::depthRange(0.01, 1.0);
365 
366  render( _state, true);
367 
368  ACG::GLState::depthRange(0.0, 1.0);
369  }
370 
371 
372  if ( ( _drawMode & DrawModes::SOLID_SMOOTH_SHADED ) )
373  {
374  ACG::GLState::enable(GL_AUTO_NORMAL);
375  ACG::GLState::enable(GL_NORMALIZE);
376 
377  ACG::GLState::enable(GL_LIGHTING);
378  ACG::GLState::shadeModel(GL_SMOOTH);
379  ACG::GLState::depthRange(0.01, 1.0);
380 
381  render( _state, true);
382 
383  ACG::GLState::depthRange(0.0, 1.0);
384  }
385 
386  if ( ( _drawMode & DrawModes::SOLID_PHONG_SHADED ) )
387  {
388  ACG::GLState::enable(GL_AUTO_NORMAL);
389  ACG::GLState::enable(GL_NORMALIZE);
390 
391  ACG::GLState::enable(GL_LIGHTING);
392  ACG::GLState::shadeModel(GL_SMOOTH);
393  ACG::GLState::depthRange(0.01, 1.0);
394 
395  render( _state, true);
396 
397  ACG::GLState::depthRange(0.0, 1.0);
398  }
399 
400 
401  // If in shader mode, just draw, as the shader has to be set by a shadernode above this node
402  if ( (_drawMode & DrawModes::SOLID_SHADER ) ) {
403  ACG::GLState::enable(GL_AUTO_NORMAL);
404  ACG::GLState::enable(GL_NORMALIZE);
405 
406  ACG::GLState::enable(GL_LIGHTING);
407  ACG::GLState::shadeModel(GL_SMOOTH);
408  ACG::GLState::depthRange(0.01, 1.0);
409 
410 // draw_faces(PER_VERTEX);
411  render( _state, true);
412 
413  ACG::GLState::depthRange(0.0, 1.0);
414  }
415 
416 
417  if ((_drawMode & DrawModes::SOLID_TEXTURED) || (_drawMode & DrawModes::SOLID_ENV_MAPPED)) {
418  ACG::GLState::enable(GL_AUTO_NORMAL);
419  ACG::GLState::enable(GL_NORMALIZE);
420 // ACG::GLState::enable (GL_BLEND);
421 // ACG::GLState::blendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
422  ACG::GLState::enable(GL_LIGHTING);
423  ACG::GLState::shadeModel(GL_SMOOTH);
424  ACG::GLState::depthRange(0.01, 1.0);
425 
426  arb_texture_used_ = true;
427  drawTexturedSurface(_state, arb_texture_idx_ );
428  arb_texture_used_ = false;
429 
430  ACG::GLState::depthRange(0.0, 1.0);
431 // ACG::GLState::disable(GL_BLEND);
432  }
433 
434  glPopAttrib();
435 }
436 
437 //----------------------------------------------------------------------------
438 
439 template <class BSplineSurfaceType>
440 void
442 render(GLState& _state, bool _fill)
443 {
444  // draw the control net (includes selection on the net)
445  if (render_control_net_)
446  {
447  if (bspline_draw_mode_ == NORMAL)
448  drawControlNet(_state);
449  else if (bspline_draw_mode_ == FANCY)
450  drawFancyControlNet(_state);
451  }
452 
453  // draw the spline curve itself, depending on the type of visualization
454  if (render_bspline_surface_)
455  {
456  if (bspline_selection_draw_mode_ == NONE)
457  drawSurface(_state, _fill);
458  else if (bspline_selection_draw_mode_ == CONTROLPOINT)
459  drawTexturedSurface(_state, cp_selection_texture_idx_);
460  else if (bspline_selection_draw_mode_ == KNOTVECTOR)
461  drawTexturedSurface(_state, knot_selection_texture_idx_);
462  }
463 }
464 
465 //----------------------------------------------------------------------------
466 
467 template <class BSplineSurfaceType>
468 void
470 drawSurface(GLState& _state, bool _fill)
471 {
472  updateSurfaceMesh();
473 
474  surfaceVBO_.bind();
475  surfaceIBO_.bind();
476 
477  surfaceDecl_.activateFixedFunction();
478 
479  // draw
480  glDrawElements(GL_TRIANGLES, surfaceIndexCount_, GL_UNSIGNED_INT, 0);
481 
482  surfaceDecl_.deactivateFixedFunction();
483 
484  surfaceIBO_.unbind();
485  surfaceVBO_.unbind();
486 }
487 
488 //----------------------------------------------------------------------------
489 
490 template <class BSplineSurfaceType>
491 void
493 drawTexturedSurface(GLState& _state, GLuint _texture_idx)
494 {
495  glPushAttrib(GL_ALL_ATTRIB_BITS);
496 // ACG::GLState::enable( GL_COLOR_MATERIAL );
497 // glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
498 
499  ACG::GLState::enable(GL_TEXTURE_2D);
500 
501  // blend colors (otherwise lighting does not affect the texture)
502  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
503  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
504  // avoid aliasing at patch boundaries
505  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
506  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
507 
508  // repeat if arbitrary texture mode
509  if( arb_texture_used_ )
510  {
511  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
512  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
513  }
514 
515  // GL_MODULATE to include lighting effects
516  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
517 
518  ACG::GLState::bindTexture( GL_TEXTURE_2D, _texture_idx);
519 
520  drawSurface( _state);
521 
522  ACG::GLState::bindTexture( GL_TEXTURE_2D, 0);
523  ACG::GLState::disable(GL_TEXTURE_2D);
524 // ACG::GLState::disable( GL_COLOR_MATERIAL );
525  glPopAttrib( );
526 }
527 
528 //----------------------------------------------------------------------------
529 
530 template <class BSplineSurfaceType>
531 void
533 drawControlNet(GLState& _state)
534 {
535  // remember old color
536  Vec4f base_color_old = _state.base_color();
537 
538  // draw control net
539 // glPushAttrib(GL_ENABLE_BIT);
540  glPushAttrib(GL_ALL_ATTRIB_BITS);
541 
542  ACG::GLState::disable( GL_CULL_FACE );
543  ACG::GLState::disable(GL_LIGHTING);
544  ACG::GLState::shadeModel(GL_FLAT);
545 
546 
547  // update controlnet buffers
548  updateControlNetMesh();
549  updateControlNetMeshSel();
550 
551  // bind vbo containing all control points
552  controlNetVBO_.bind();
553  controlNetDecl_.activateFixedFunction();
554 
555  // draw points
556 
557  // draw selection
558  if (controlNetSelIndices_)
559  {
560  glColor(generateHighlightColor(controlnet_color_));
561  glPointSize(10);
562 
563  // selected points are in index buffer
564  controlNetSelIBO_.bind();
565  glDrawElements(GL_POINTS, controlNetSelIndices_, GL_UNSIGNED_INT, 0);
566  }
567 
568  // draw all points
569  glColor(controlnet_color_);
570 
571  float point_size_old = _state.point_size();
572  glPointSize(point_size_old + 4);
573 
574  GLsizei numControlPoints = bsplineSurface_.n_control_points_m() * bsplineSurface_.n_control_points_n();
575  glDrawArrays(GL_POINTS, 0, numControlPoints);
576 
577  glPointSize((int)point_size_old);
578 
579 
580  // draw line segments
581 
582  /*
583  // draw selection
584  if( bsplineSurface_.edge_selections_available())
585  {
586  // save old values
587  Vec4f base_color_old = _state.base_color();
588  float line_width_old = _state.line_width();
589 
590  glColor(controlnet_highlight_color_);
591  glLineWidth(2*line_width_old);
592 
593  glBegin(GL_LINES);
594  // draw bspline control net
595  int num_edges_m = (int)(bsplineSurface_.n_control_points_m()) - 1;
596  int num_edges_n = (int)(bsplineSurface_.n_control_points_n()) - 1;
597  for (int i = 0; i < num_edges_m; ++i) // #edges
598  {
599  for (int j = 0; j < num_edges_n; ++j) // #edges
600  {
601  if( bsplineSurface_.edge_selection(i, j))
602  {
603  glVertex(bsplineSurface_(i,j));
604  glVertex(bsplineSurface_(i+1, j));
605  }
606  }
607  }
608  glEnd();
609 
610  glLineWidth(line_width_old);
611  glColor( base_color_old );
612  }
613 */
614  // draw all line segments
615  glColor(controlnet_color_);
616 
617  float line_width_old = _state.line_width();
618  glLineWidth(line_width_old+2.0);
619 
620  controlNetLineIBO_.bind();
621  glDrawElements(GL_LINES, controlNetLineIndices_, GL_UNSIGNED_INT, 0);
622 
623 
624  // restore gl states
625  controlNetDecl_.deactivateFixedFunction();
626  controlNetLineIBO_.unbind();
627  controlNetVBO_.unbind();
628 
629  glColor( base_color_old );
630  glLineWidth(line_width_old);
631 
632  glPopAttrib();
633 }
634 
635 //----------------------------------------------------------------------------
636 
637 template <class BSplineSurfaceType>
638 void
641 {
642  // remember old color
643  Vec4f base_color_old = _state.base_color();
644 
645  // draw control net
646 // glPushAttrib(GL_ENABLE_BIT);
647  glPushAttrib(GL_ALL_ATTRIB_BITS);
648 
649  ACG::GLState::disable( GL_CULL_FACE );
650 
651  glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
652  ACG::GLState::enable( GL_COLOR_MATERIAL );
653  ACG::GLState::enable(GL_LIGHTING);
654  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
655  ACG::GLState::shadeModel(GL_SMOOTH);
656 
657 
658  // draw points
659  double sphereRadius = _state.point_size() * 0.05;
660 
661  // draw selection
662  if( bsplineSurface_.controlpoint_selections_available())
663  {
664  // save old values
665  float point_size_old = _state.point_size();
666 
667  // save old values
668 // glColor(controlnet_highlight_color_);
669  glColor(generateHighlightColor(controlnet_color_));
670 
671  // draw control polygon
672  for (unsigned int i = 0; i < bsplineSurface_.n_control_points_m(); ++i)
673  {
674  for (unsigned int j = 0; j < bsplineSurface_.n_control_points_n(); ++j)
675  {
676  if( bsplineSurface_.controlpoint_selection(i, j))
677  draw_sphere(bsplineSurface_(i, j), sphereRadius, _state, fancySphere_);
678  }
679  }
680 
681  glPointSize(point_size_old);
682  }
683 
684  // draw all points
685  glColor(controlnet_color_);
686 
687  for (unsigned int i = 0; i < bsplineSurface_.n_control_points_m(); ++i)
688  for (unsigned int j = 0; j < bsplineSurface_.n_control_points_n(); ++j)
689  draw_sphere(bsplineSurface_(i, j), sphereRadius, _state, fancySphere_);
690 
691 
692  // draw line segments
693 
694  double cylinderRadius = _state.line_width() * 0.05;
695 
696  glColor(controlnet_color_);
697 
698  // draw bspline control net
699  for (unsigned int i = 0; i < bsplineSurface_.n_control_points_m(); ++i)
700  {
701  for (int j = 0; j < (int)bsplineSurface_.n_control_points_n() - 1; ++j)
702  {
703  Vec3d p = bsplineSurface_(i, j);
704  Vec3d p_next = bsplineSurface_(i, j+1);
705  draw_cylinder(p, p_next - p, cylinderRadius, _state);
706  }
707  }
708 
709  for (int j = 0; j < (int)bsplineSurface_.n_control_points_n(); ++j)
710  {
711  for (int i = 0; i < (int)bsplineSurface_.n_control_points_m() - 1; ++i)
712  {
713  Vec3d p = bsplineSurface_(i, j);
714  Vec3d p_next = bsplineSurface_(i+1,j);
715  draw_cylinder(p, p_next - p, cylinderRadius, _state);
716  }
717  }
718 
719  // reset old color
720  glColor( base_color_old );
721 
722  glPopAttrib();
723 }
724 
725 //----------------------------------------------------------------------------
726 
727 template <class BSplineSurfaceType>
728 void
731 {
732  invalidateSurfaceMesh_ = true;
733  invalidateControlNetMesh_ = true;
734 }
735 
736 //----------------------------------------------------------------------------
737 
738 template <class BSplineSurfaceType>
739 void
741 pick(GLState& _state, PickTarget _target)
742 {
743  if(pick_texture_idx_ == 0)
744  pick_init_texturing();
745 
746  ACG::GLState::disable(GL_COLOR_MATERIAL);
747 
748  switch (_target)
749  {
750  case PICK_VERTEX:
751  {
752  if(render_control_net_)
753  {
754  _state.pick_set_maximum (bsplineSurface_.n_control_points_m() * bsplineSurface_.n_control_points_n());
755  pick_vertices(_state);
756  }
757  break;
758  }
759 
760  case PICK_FACE:
761  {
762  _state.pick_set_maximum (1);
763  pick_surface(_state, 0);
764  break;
765  }
766 
767  case PICK_SPLINE:
768  {
769  _state.pick_set_maximum( pick_texture_res_ * pick_texture_res_);
770  pick_spline(_state);
771  break;
772  }
773 
774  case PICK_ANYTHING:
775  {
776  _state.pick_set_maximum (bsplineSurface_.n_control_points_m() * bsplineSurface_.n_control_points_n() + 1);
777  pick_vertices(_state);
778  pick_surface(_state, bsplineSurface_.n_control_points_m() * bsplineSurface_.n_control_points_n());
779  break;
780  }
781 
782  default:
783  break;
784  }
785 }
786 
787 //----------------------------------------------------------------------------
788 
789 template <class BSplineSurfaceType>
790 void
792 pick_vertices( GLState& _state )
793 {
794  // radius in pixels
795  int psize = 7;
796 
797  _state.pick_set_name (0);
798 
799  for (unsigned int i = 0; i < bsplineSurface_.n_control_points_m(); ++i)
800  {
801  for (unsigned int j = 0; j < bsplineSurface_.n_control_points_n(); ++j)
802  {
803  _state.pick_set_name (i * bsplineSurface_.n_control_points_n() + j);
804 
805  // compute 3d radius of sphere
806  Vec3d window_pos = _state.project( (Vec3d)bsplineSurface_(i,j) );
807  int px = round( window_pos[0]);
808  int py = round( window_pos[1]);
809  double angle = acos(_state.viewing_direction(px, py).normalize()|_state.viewing_direction(px+psize, py).normalize());
810  double l = (_state.eye() - (Vec3d)bsplineSurface_(i,j)).norm();
811  double r = l*tan(angle);
812 
813  // draw 3d sphere
814  draw_sphere( bsplineSurface_(i,j), r, _state, sphere_);
815  }
816  }
817 }
818 
819 //----------------------------------------------------------------------------
820 
821 template <class BSplineSurfaceType>
822 void
824 pick_spline( GLState& _state )
825 {
826  glPushAttrib(GL_ALL_ATTRIB_BITS);
827 
828  ACG::GLState::enable(GL_TEXTURE_2D);
829 
830  ACG::GLState::disable(GL_COLOR_MATERIAL);
831  ACG::GLState::disable(GL_LIGHTING);
832  ACG::GLState::shadeModel(GL_FLAT);
833 
834  std::cout << "[BSplineSurface] pick_spline: \n"
835  << "pick_texture_baseidx_ = " << pick_texture_baseidx_
836  << ", _state.pick_current_index () = " << _state.pick_current_index ()
837  << ", pick_texture_idx_ = " << pick_texture_idx_
838  << std::endl;
839 
840  if( _state.pick_current_index () != pick_texture_baseidx_)
841  {
842  pick_texture_baseidx_ = _state.pick_current_index();
843  pick_create_texture( _state);
844  }
845  else
846  {
847  // do not blend colors (else color picking breaks!)
848  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
849  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
850  // avoid aliasing at patch boundaries
851  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
852  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
853  // GL_REPLACE to avoid smearing colors (else color picking breaks!)
854  glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
855 
856  ACG::GLState::bindTexture( GL_TEXTURE_2D, pick_texture_idx_);
857  }
858 
859  drawSurface(_state);
860 
861  ACG::GLState::bindTexture( GL_TEXTURE_2D, 0);
862  ACG::GLState::disable(GL_TEXTURE_2D);
863  glPopAttrib( );
864 }
865 
866 //----------------------------------------------------------------------------
867 
868 template <class BSplineSurfaceType>
869 void
871 pick_surface( GLState& _state, unsigned int _offset )
872 {
873  bool sampling_mode_backup = adaptive_sampling_;
874  adaptive_sampling_ = false;
875 
876  // pick the whole surface
877  _state.pick_set_name ( _offset );
878  drawSurface( _state);
879 
880  adaptive_sampling_ = sampling_mode_backup;
881 }
882 
883 //----------------------------------------------------------------------------
884 
885 template <class BSplineSurfaceType>
886 void
888 draw_sphere( const Point& _p0, double _r, GLState& _state, GLSphere* _sphere)
889 {
890  // draw 3d sphere
891  _state.push_modelview_matrix();
892  _state.translate( _p0[0], _p0[1], _p0[2]);
893 
894  _sphere->draw(_state,_r);
895 
896  _state.pop_modelview_matrix();
897 }
898 
899 //----------------------------------------------------------------------------
900 
901 template <class BSplineSurfaceType>
902 void
904 draw_cylinder( const Point& _p0, const Point& _axis, double _r, GLState& _state)
905 {
906  _state.push_modelview_matrix();
907  _state.translate(_p0[0], _p0[1], _p0[2]);
908 
909  Point direction = _axis;
910  Point z_axis(0,0,1);
911  Point rot_normal;
912  double rot_angle;
913 
914  direction.normalize();
915  rot_angle = acos((z_axis | direction))*180/M_PI;
916  rot_normal = ((z_axis % direction).normalize());
917 
918  if( fabs( rot_angle ) > 0.0001 && fabs( 180 - rot_angle ) > 0.0001)
919  _state.rotate(rot_angle,rot_normal[0], rot_normal[1], rot_normal[2]);
920  else
921  _state.rotate(rot_angle,1,0,0);
922 
923  cylinder_->setBottomRadius(_r);
924  cylinder_->setTopRadius(_r);
925  cylinder_->draw(_state,_axis.norm());
926 
927  _state.pop_modelview_matrix();
928 }
929 
930 //----------------------------------------------------------------------------
931 
932 template <class BSplineSurfaceType>
933 void
936 {
937  create_cp_selection_texture(_state);
938  controlPointSelectionTexture_valid_ = true;
939 
940  // also update index buffer for rendering selections
941  invalidateControlNetMeshSel_ = true;
942 }
943 
944 //----------------------------------------------------------------------------
945 
946 template <class BSplineSurfaceType>
947 void
950 {
951  create_knot_selection_texture(_state);
952  knotVectorSelectionTexture_valid_ = true;
953 }
954 
955 //----------------------------------------------------------------------------
956 
957 template <class BSplineSurfaceType>
958 void
960 selection_init_texturing(GLuint & _texture_idx )
961 {
962  // generate texture index
963  glGenTextures( 1, &_texture_idx );
964  // bind texture as current
965  ACG::GLState::bindTexture( GL_TEXTURE_2D, _texture_idx );
966  // blend colors (otherwise lighting does not affect the texture)
967  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
968  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
969  // avoid aliasing at patch boundaries
970  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
971  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
972  // GL_MODULATE to include lighting effects
973  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
974  // unbind current texture
975  ACG::GLState::bindTexture( GL_TEXTURE_2D, 0);
976 }
977 
978 //----------------------------------------------------------------------------
979 
980 template <class BSplineSurfaceType>
981 void
984 {
985  if (bsplineSurface_.n_knots_m() == 0 || bsplineSurface_.n_knots_n() == 0)
986  return;
987 
988  if(cp_selection_texture_idx_ == 0)
989  selection_init_texturing(cp_selection_texture_idx_);
990 
991  QImage b(cp_selection_texture_res_, cp_selection_texture_res_, QImage::Format_ARGB32);
992 
993  int degree_m = bsplineSurface_.degree_m();
994  int degree_n = bsplineSurface_.degree_n();
995 
996  int numKnots_m = bsplineSurface_.n_knots_m();
997  int numKnots_n = bsplineSurface_.n_knots_n();
998 
999  Knotvector knotvec_m = bsplineSurface_.get_knotvector_m();
1000  Knotvector knotvec_n = bsplineSurface_.get_knotvector_n();
1001 
1002  double minu = bsplineSurface_.get_knot_m( degree_m );
1003  double maxu = bsplineSurface_.get_knot_m( numKnots_m - degree_m -1 );
1004  double diffu = maxu - minu;
1005 
1006  double minv = bsplineSurface_.get_knot_n( degree_n );
1007  double maxv = bsplineSurface_.get_knot_n( numKnots_n - degree_n -1 );
1008  double diffv = maxv - minv;
1009 
1010  if (diffu == 0.0 || diffv == 0.0 )
1011  return;
1012 
1013  int texelIdx_u = 0;
1014 
1015  for ( int m = 0; m < cp_selection_texture_res_; ++m)
1016  {
1017  double step_m = (double)m / (double)cp_selection_texture_res_;
1018  double u = step_m * diffu;
1019 
1020  // get the span and check which knots are selected
1021  ACG::Vec2i span_u = bsplineSurface_.spanm(u);
1022  // check for incomplete spline
1023  if (span_u[0] < 0 || span_u[1] < 0)
1024  return;
1025 
1026  // reset texture v coord for every new u coord
1027  int texelIdx_v = 0;
1028 
1029  // iterate over n direction
1030  for ( int n = 0; n < cp_selection_texture_res_; ++n)
1031  {
1032  double step_n = double(n) / (double)cp_selection_texture_res_;
1033  double v = step_n * diffv;
1034 
1035  // get the span and check which knots are selected
1036  ACG::Vec2i span_v = bsplineSurface_.spann(v);
1037  // check for incomplete spline
1038  if (span_v[0] < 0 || span_v[1] < 0)
1039  return;
1040 
1041  float alpha = 0.0; // blends between curve and highlight colors
1042  for (int i = 0; i < degree_m+1; ++i) // degree+1 basis functions (those in the span) contribute
1043  {
1044  int idx_m = span_u[0] + i;
1045 
1046  for (int j = 0; j < degree_n+1; ++j) // degree+1 basis functions (those in the span) contribute
1047  {
1048  int idx_n = span_v[0] + j;
1049 
1050  // basis functions sum up to 1. hence, we only have to sum up those with selected control point to get the blending weight
1051  if (bsplineSurface_.controlpoint_selection(idx_m, idx_n))
1052  alpha += bsplineSurface_.basisFunction( knotvec_m, idx_m, degree_m, u)
1053  * bsplineSurface_.basisFunction( knotvec_n, idx_n, degree_n, v);
1054  }
1055  }
1056 
1057  // compute color
1058  Vec4f color = surface_color_ * (1.0 - alpha) + surface_highlight_color_ * alpha;
1059 
1060  // fill texture (switch v coord due to axis of texture image)
1061  b.setPixel (texelIdx_u, 255-texelIdx_v, qRgba((int)(color[0]*255.0), (int)(color[1]*255.0), (int)(color[2]*255.0), 255));
1062 
1063  ++texelIdx_v;
1064  } // end of n direction iter
1065 
1066  ++texelIdx_u;
1067  } // end of u direction iter
1068 
1069 
1070  // debug, output image
1071 // b.save("surfaceCPSelectionTexture.png", "PNG");
1072 
1073  cp_selection_texture_image_ = QGLWidget::convertToGLFormat( b );
1074 
1075  // bind texture
1076  ACG::GLState::bindTexture( GL_TEXTURE_2D, cp_selection_texture_idx_ );
1077  glTexImage2D( GL_TEXTURE_2D,
1078  0, GL_RGBA, cp_selection_texture_image_.width(), cp_selection_texture_image_.height(),
1079  0, GL_RGBA, GL_UNSIGNED_BYTE, cp_selection_texture_image_.bits() );
1080 }
1081 
1082 //----------------------------------------------------------------------------
1083 
1084 template <class BSplineSurfaceType>
1085 void
1088 {
1089  if (bsplineSurface_.n_knots_m() == 0 ||bsplineSurface_.n_knots_n() == 0)
1090  return;
1091 
1092  if(knot_selection_texture_idx_ == 0)
1093  selection_init_texturing(knot_selection_texture_idx_);
1094 
1095  QImage b(knot_selection_texture_res_, knot_selection_texture_res_, QImage::Format_ARGB32);
1096 
1097  int degree_m = bsplineSurface_.degree_m();
1098  int degree_n = bsplineSurface_.degree_n();
1099 
1100  int numKnots_m = bsplineSurface_.n_knots_m();
1101  int numKnots_n = bsplineSurface_.n_knots_n();
1102 
1103  Knotvector knotvec_m = bsplineSurface_.get_knotvector_m();
1104  Knotvector knotvec_n = bsplineSurface_.get_knotvector_n();
1105 
1106  double minu = bsplineSurface_.get_knot_m( degree_m );
1107  double maxu = bsplineSurface_.get_knot_m( numKnots_m - degree_m -1 );
1108  double diffu = maxu - minu;
1109 
1110  double minv = bsplineSurface_.get_knot_n( degree_n );
1111  double maxv = bsplineSurface_.get_knot_n( numKnots_n - degree_n -1 );
1112  double diffv = maxv - minv;
1113 
1114  if (diffu == 0.0 || diffv == 0.0 )
1115  return;
1116 
1117  int texelIdx_u = 0;
1118 
1119  // if a knot is selected, select all knots in the span of this knot, too
1120  std::vector<bool> selectedKnotSpans_m(numKnots_m, false);
1121  for (int i = 0; i < numKnots_m; ++i)
1122  {
1123  if (bsplineSurface_.get_knotvector_m_ref()->selection(i))
1124  {
1125  // get the span and check which knots are selected
1126  ACG::Vec2i span = bsplineSurface_.spanm(bsplineSurface_.get_knot_m(i));
1127  // check for incomple spline
1128  if (span[0] < 0 || span[1] < 0)
1129  return;
1130 
1131  for(int j = span[0]; j <= span[1]+degree_m; ++j)
1132  selectedKnotSpans_m[j] = true;
1133  }
1134  }
1135 // std::cout << "selectedKnotSpans_m: " << std::flush;
1136 // for (unsigned int i = 0; i < selectedKnotSpans_m.size(); ++i)
1137 // std::cout << selectedKnotSpans_m[i] << ", " << std::flush;
1138 // std::cout << std::endl;
1139 
1140 
1141  std::vector<bool> selectedKnotSpans_n(numKnots_n, false);
1142  for (int i = 0; i < numKnots_n; ++i)
1143  {
1144  if (bsplineSurface_.get_knotvector_n_ref()->selection(i))
1145  {
1146  // get the span and check which knots are selected
1147  ACG::Vec2i span = bsplineSurface_.spann(bsplineSurface_.get_knot_n(i));
1148  // check for incomple spline
1149  if (span[0] < 0 || span[1] < 0)
1150  return;
1151 
1152  for(int j = span[0]; j <= span[1]+degree_n; ++j)
1153  selectedKnotSpans_n[j] = true;
1154  }
1155  }
1156 // std::cout << "selectedKnotSpans_n: " << std::flush;
1157 // for (unsigned int i = 0; i < selectedKnotSpans_n.size(); ++i)
1158 // std::cout << selectedKnotSpans_n[i] << ", " << std::flush;
1159 // std::cout << std::endl;
1160 
1161 
1162  for ( int m = 0; m < knot_selection_texture_res_; ++m)
1163  {
1164  double step_m = (double)m / (double)knot_selection_texture_res_;
1165  double u = step_m * diffu;
1166 
1167  Vec2i interval_m = bsplineSurface_.interval_m(u);
1168 
1169  // reset texture v coord for every new u coord
1170  int texelIdx_v = 0;
1171 
1172  for ( int n = 0; n < knot_selection_texture_res_; ++n)
1173  {
1174  double step_n = (double)n / (double)knot_selection_texture_res_;
1175  double v = step_n * diffv;
1176 
1177  Vec2i interval_n = bsplineSurface_.interval_n(v);
1178 
1179  // check if highlighted
1180  bool selected_m = (selectedKnotSpans_m[interval_m[0]] && selectedKnotSpans_m[interval_m[1]]);
1181  bool selected_n = (selectedKnotSpans_n[interval_n[0]] && selectedKnotSpans_n[interval_n[1]]);
1182 
1183  Vec4f color;
1184  if (selected_m && selected_n)
1185 // color = _state.specular_color();
1186 // color = _state.base_color();
1187  color = surface_highlight_color_;
1188  else if ((selected_m && !selected_n) || (!selected_m && selected_n) )
1189 // color = _state.ambient_color() *0.5 + _state.specular_color() * 0.5;
1190 // color = _state.base_color() *0.5 + _state.specular_color() * 0.5;
1191  color = surface_highlight_color_ * 0.5 + surface_color_ * 0.5;
1192  else
1193 // color = _state.ambient_color() *0.5 + _state.diffuse_color() * 0.5;
1194 // color = _state.base_color() *0.5 + _state.diffuse_color() * 0.5;
1195  color = surface_color_;
1196 
1197 
1198  // fill texture
1199  b.setPixel (texelIdx_u, 255-texelIdx_v, qRgba((int)(color[0]*255.0), (int)(color[1]*255.0), (int)(color[2]*255.0), 255));
1200 
1201  ++texelIdx_v;
1202  } // end of v direction
1203 
1204  ++texelIdx_u;
1205  } // end of u direction
1206 
1207  // debug, output image
1208 // b.save("surfaceKnotSelectionTexture.png", "PNG");
1209 
1210  knot_selection_texture_image_ = QGLWidget::convertToGLFormat( b );
1211 
1212  // bind texture
1213  ACG::GLState::bindTexture( GL_TEXTURE_2D, knot_selection_texture_idx_ );
1214  glTexImage2D( GL_TEXTURE_2D,
1215  0, GL_RGBA, knot_selection_texture_image_.width(), knot_selection_texture_image_.height(),
1216  0, GL_RGBA, GL_UNSIGNED_BYTE, knot_selection_texture_image_.bits() );
1217 }
1218 
1219 //----------------------------------------------------------------------------
1220 
1221 template <class BSplineSurfaceType>
1222 void
1225 {
1226  std::cout << "[BSplineSurface] pick_init_texturing()" << std::endl;
1227 
1228  pick_texture_res_ = 256;
1229  pick_texture_baseidx_ = 0;
1230 
1231  // generate texture index
1232  glGenTextures( 1, &pick_texture_idx_ );
1233  // bind texture as current
1234  ACG::GLState::bindTexture( GL_TEXTURE_2D, pick_texture_idx_ );
1235  // do not blend colors (else color picking breaks!)
1236  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
1237  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
1238  // avoid aliasing at patch boundaries
1239  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
1240  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
1241  // GL_REPLACE to avoid smearing colors (else color picking breaks!)
1242  glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1243  // unbind current texture
1244  ACG::GLState::bindTexture( GL_TEXTURE_2D, 0);
1245 }
1246 
1247 //----------------------------------------------------------------------------
1248 
1249 template <class BSplineSurfaceType>
1250 void
1253 {
1254  std::cout << "[BSplineSurface] pick_create_texture()" << std::endl;
1255 
1256  QImage b(pick_texture_res_, pick_texture_res_, QImage::Format_ARGB32);
1257  QImage texture(pick_texture_res_, pick_texture_res_, QImage::Format_ARGB32);
1258 
1259  // fill with colors
1260  int cur_idx=0;
1261  for( int i = 0; i < pick_texture_res_; ++i)
1262  {
1263  for( int j = pick_texture_res_ - 1; j >= 0; j--)
1264  {
1265  Vec4uc cur_col( _state.pick_get_name_color (cur_idx) );
1266  b.setPixel ( i,j, qRgba((int)cur_col[0], (int)cur_col[1], (int)cur_col[2], (int)cur_col[3]));
1267 
1268  Vec4f testcol = Vec4f((float)cur_col[0], (float)cur_col[1], (float)cur_col[2], (float)cur_col[3]);
1269  texture.setPixel ( i,j, qRgba((int)(testcol[0]*255.0), (int)(testcol[1]*255.0), (int)(testcol[2]*255.0), 255));
1270  cur_idx++;
1271  }
1272  }
1273 
1274 /*
1275  // creates checkerboard texture for debugging purposes
1276 
1277  bool odd_row = true;
1278  bool odd_col = true;
1279  bool green = true;
1280  for( int i = 0; i < pick_texture_res_; ++i)
1281  {
1282  if (i % 20 == 0)
1283  odd_row = !odd_row;
1284 
1285  odd_col = true;
1286  for( int j = 0; j < pick_texture_res_; ++j)
1287  {
1288  if (j % 20 == 0)
1289  odd_col = !odd_col;
1290 
1291  green = (odd_row && odd_col) || (!odd_row && !odd_col);
1292 
1293  if (green)
1294  b.setPixel (i, j, qRgba(0, 255, 0, 255));
1295  else
1296  b.setPixel (i, j, qRgba(255, 0, 255, 255));
1297  }
1298  }
1299 */
1300 
1301  // debug, output image
1302 // b.save("surfacePickingTexture.png", "PNG");
1303  texture.save("surfacePickingTexture.png", "PNG");
1304 
1305  pick_texture_image_ = QGLWidget::convertToGLFormat( b );
1306 
1307  // bind texture
1308  ACG::GLState::bindTexture( GL_TEXTURE_2D, pick_texture_idx_ );
1309  glTexImage2D( GL_TEXTURE_2D,
1310  0, GL_RGBA, pick_texture_image_.width(), pick_texture_image_.height(),
1311  0, GL_RGBA, GL_UNSIGNED_BYTE, pick_texture_image_.bits() );
1312 }
1313 
1314 //----------------------------------------------------------------------------
1315 
1316 template <class BSplineSurfaceType>
1317 void
1319 set_arb_texture( const QImage& _texture, bool _repeat, float _u_repeat, float _v_repeat )
1320 {
1321  if(arb_texture_idx_ == 0)
1322  selection_init_texturing(arb_texture_idx_);
1323 
1324  ACG::GLState::bindTexture( GL_TEXTURE_2D, 0);
1325 
1326  arb_texture_repeat_ = _repeat;
1327  arb_texture_repeat_u_ = _u_repeat;
1328  arb_texture_repeat_v_ = _v_repeat;
1329 
1330  arb_texture_image_ = QGLWidget::convertToGLFormat( _texture );
1331  int u_res = arb_texture_image_.width();
1332  int v_res = arb_texture_image_.height();
1333 
1334  // bind texture as current
1335  ACG::GLState::bindTexture( GL_TEXTURE_2D, arb_texture_idx_ );
1336 
1337  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
1338  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
1339 
1340  glTexImage2D( GL_TEXTURE_2D,
1341  0, GL_RGBA, u_res, v_res,
1342  0, GL_RGBA, GL_UNSIGNED_BYTE, arb_texture_image_.bits() );
1343 
1344  // unbind current texture
1345  ACG::GLState::bindTexture( GL_TEXTURE_2D, 0);
1346 }
1347 
1348 //----------------------------------------------------------------------------
1349 
1350 template <class BSplineSurfaceType>
1351 ACG::Vec4f
1354 {
1355  float c1 = _color[0]*1.5;
1356  c1 = c1 > 255.0 ? 255 : c1;
1357 
1358  float c2 = _color[1]*1.5;
1359  c2 = c2 > 255.0 ? 255 : c2;
1360 
1361  float c3 = _color[2]*1.5;
1362  c3 = c3 > 255.0 ? 255 : c3;
1363 
1364  return Vec4f( c1, c2, c3, _color[3]);
1365 }
1366 
1367 //----------------------------------------------------------------------------
1368 
1369 template <class BSplineSurfaceType>
1370 void
1372 updateSurfaceMesh(int _vertexCountU, int _vertexCountV)
1373 {
1374  if (!invalidateSurfaceMesh_)
1375  return;
1376 
1377  surfaceVBO_.del();
1378  surfaceIBO_.del();
1379 
1380  // vertex layout:
1381  // float3 pos
1382  // float3 normal
1383  // float2 texcoord
1384  // + debug info (optional)
1385 
1386  // provide expected values of bspline evaluation steps for debugging in shader
1387  const bool provideDebugInfo = false;
1388 
1389  if (!surfaceDecl_.getNumElements())
1390  {
1391  surfaceDecl_.addElement(GL_FLOAT, 3, VERTEX_USAGE_POSITION);
1392  surfaceDecl_.addElement(GL_FLOAT, 3, VERTEX_USAGE_NORMAL);
1393  surfaceDecl_.addElement(GL_FLOAT, 2, VERTEX_USAGE_TEXCOORD);
1394 
1395  if (provideDebugInfo)
1396  {
1397  surfaceDecl_.addElement(GL_FLOAT, 2, VERTEX_USAGE_SHADER_INPUT, size_t(0), "a2v_span");
1398  surfaceDecl_.addElement(GL_FLOAT, 4, VERTEX_USAGE_SHADER_INPUT, size_t(0), "a2v_bvu");
1399  surfaceDecl_.addElement(GL_FLOAT, 4, VERTEX_USAGE_SHADER_INPUT, size_t(0), "a2v_bvv");
1400  }
1401  }
1402 
1403  // create vertex buffer
1404 
1405  int numU = _vertexCountU,
1406  numV = _vertexCountV;
1407 
1408  GLsizeiptr vboSize = numU * numV * surfaceDecl_.getVertexStride(); // bytes
1409  std::vector<float> vboData(vboSize / 4); // float: 4 bytes
1410 
1411  // write counter
1412  int elementOffset = 0;
1413 
1414  for (int i = 0; i < numU; ++i)
1415  {
1416  // param in [0, 1]
1417  float u01 = float(i) / float(numU - 1);
1418 
1419  // map to actual range
1420  float u = (1 - u01) * bsplineSurface_.loweru() + u01 * bsplineSurface_.upperu();
1421 
1422  for (int k = 0; k < numV; ++k)
1423  {
1424  // param in [0, 1]
1425  float v01 = float(k) / float(numV - 1);
1426 
1427  // map to actual range
1428  float v = (1 - v01) * bsplineSurface_.lowerv() + v01 * bsplineSurface_.upperv();
1429 
1430  // evaluate
1431  Point pos, normal;
1432  bsplineSurface_.surfacePointNormal(pos, normal, u, v);
1433 
1434  // store pos
1435  for (int m = 0; m < 3; ++m)
1436  vboData[elementOffset++] = float(pos[m]);
1437 
1438  // store normal
1439  for (int m = 0; m < 3; ++m)
1440  vboData[elementOffset++] = float(normal[m]);
1441 
1442  // store texcoord
1443  vboData[elementOffset++] = u01;
1444  vboData[elementOffset++] = v01;
1445 
1446 
1447  if (provideDebugInfo)
1448  {
1449  // debug elements
1450  Vec2i span_u = bsplineSurface_.spanm(u);
1451  Vec2i span_v = bsplineSurface_.spann(u);
1452  vboData[elementOffset++] = span_u[1];
1453  vboData[elementOffset++] = span_v[1];
1454 
1455  std::vector<typename Point::value_type> bvu(std::max(4, bsplineSurface_.degree_m() + 1), 0);
1456  std::vector<typename Point::value_type> bvv(std::max(4, bsplineSurface_.degree_n() + 1), 0);
1457  bsplineBasisFunctions<typename Point::value_type>(bvu, span_u, u, bsplineSurface_.get_knotvector_m().getKnotvector());
1458  bsplineBasisFunctions<typename Point::value_type>(bvv, span_v, v, bsplineSurface_.get_knotvector_n().getKnotvector());
1459 
1460  for (int m = 0; m < 4; ++m) vboData[elementOffset++] = bvu[m];
1461  for (int m = 0; m < 4; ++m) vboData[elementOffset++] = bvv[m];
1462  }
1463  }
1464  }
1465 
1466  if (vboSize)
1467  surfaceVBO_.upload(vboSize, &vboData[0], GL_STATIC_DRAW);
1468 
1469  vboData.clear();
1470 
1471 
1472 
1473  // create index buffer
1474  int numIndices = (numU - 1) * (numV - 1) * 6;
1475  std::vector<int> iboData(numIndices);
1476 
1477  // index counter
1478  int idxOffset = 0;
1479 
1480  for (int k = 0; k < numV - 1; ++k)
1481  {
1482  for (int i = 0; i < numU - 1; ++i)
1483  {
1484  /*
1485  ccw quad tessellation:
1486  c---d
1487  | / |
1488  |/ |
1489  a---b
1490  */
1491 
1492  iboData[idxOffset++] = k * numU + i;
1493  iboData[idxOffset++] = (k+1) * numU + i;
1494  iboData[idxOffset++] = (k+1) * numU + i + 1;
1495 
1496  iboData[idxOffset++] = k * numU + i;
1497  iboData[idxOffset++] = (k+1) * numU + i+1;
1498  iboData[idxOffset++] = k * numU + i + 1;
1499  }
1500  }
1501 
1502  if (numIndices)
1503  surfaceIBO_.upload(numIndices * 4, &iboData[0], GL_STATIC_DRAW);
1504 
1505 
1506  surfaceIndexCount_ = numIndices;
1507 
1508 
1509  invalidateSurfaceMesh_ = false;
1510 }
1511 
1512 //----------------------------------------------------------------------------
1513 
1514 template <class BSplineSurfaceType>
1515 void
1518 {
1519  if (!invalidateControlNetMesh_)
1520  return;
1521 
1522  // vertex layout:
1523  // float3 pos
1524 
1525  if (!controlNetDecl_.getNumElements())
1526  controlNetDecl_.addElement(GL_FLOAT, 3, VERTEX_USAGE_POSITION);
1527 
1528  int numU = bsplineSurface_.n_control_points_m(),
1529  numV = bsplineSurface_.n_control_points_n();
1530 
1531  // create vertex buffer
1532  GLsizeiptr vboSize = bsplineSurface_.n_control_points_m() * bsplineSurface_.n_control_points_n() * controlNetDecl_.getVertexStride(); // bytes
1533  std::vector<float> vboData(vboSize / 4); // float: 4 bytes
1534 
1535  // write counter
1536  int elementOffset = 0;
1537 
1538  for (int k = 0; k < numV; ++k)
1539  {
1540  for (int i = 0; i < numU; ++i)
1541  {
1542  Point pt = bsplineSurface_.get_control_point(i, k);
1543  for (int m = 0; m < 3; ++m)
1544  vboData[elementOffset++] = pt[m];
1545  }
1546  }
1547 
1548  if (vboSize)
1549  controlNetVBO_.upload(vboSize, &vboData[0], GL_STATIC_DRAW);
1550 
1551  vboData.clear();
1552 
1553 
1554 
1555  // create index buffer for line segments
1556  // horizontal + vertical cross lines, 2 indices per segment
1557  int numIndices = 2 *( (numU - 1) * (numV) + (numU) * (numV - 1) );
1558  std::vector<int> iboData(numIndices);
1559 
1560  // index counter
1561  int idxOffset = 0;
1562 
1563  // horizontal lines
1564  for (int k = 0; k < numV; ++k)
1565  {
1566  for (int i = 0; i < numU - 1; ++i)
1567  {
1568  iboData[idxOffset++] = k * numU + i;
1569  iboData[idxOffset++] = k * numU + i + 1;
1570  }
1571  }
1572 
1573  // vertical lines
1574  for (int k = 0; k < numV - 1; ++k)
1575  {
1576  for (int i = 0; i < numU; ++i)
1577  {
1578  iboData[idxOffset++] = k * numU + i;
1579  iboData[idxOffset++] = (k+1) * numU + i;
1580  }
1581  }
1582 
1583  if (numIndices)
1584  controlNetLineIBO_.upload(numIndices * 4, &iboData[0], GL_STATIC_DRAW);
1585 
1586 
1587  controlNetLineIndices_ = numIndices;
1588 
1589 
1590  invalidateControlNetMesh_ = false;
1591 }
1592 
1593 //----------------------------------------------------------------------------
1594 
1595 
1596 template <class BSplineSurfaceType>
1597 void
1600 {
1601  if (!invalidateControlNetMeshSel_)
1602  return;
1603 
1604  controlNetSelIBO_.del();
1605 
1606  if (bsplineSurface_.controlpoint_selections_available())
1607  {
1608  int numU = bsplineSurface_.n_control_points_m(),
1609  numV = bsplineSurface_.n_control_points_n();
1610 
1611  // count # selected points
1612  int numSel = 0;
1613  for (int k = 0; k < numV; ++k)
1614  {
1615  for (int i = 0; i < numU; ++i)
1616  {
1617  if (bsplineSurface_.controlpoint_selection(i, k))
1618  ++numSel;
1619  }
1620  }
1621 
1622  // save count for draw call
1623  controlNetSelIndices_ = numSel;
1624 
1625 
1626  if (numSel)
1627  {
1628  // create array
1629  std::vector<int> iboData(numSel);
1630  numSel = 0;
1631  for (int k = 0; k < numV; ++k)
1632  {
1633  for (int i = 0; i < numU; ++i)
1634  {
1635  if (bsplineSurface_.controlpoint_selection(i, k))
1636  {
1637  // see vertex indexing of vbo in updateControlNetMesh()
1638  // they are in "row-mayor" order
1639  iboData[numSel++] = k * numU + i;
1640  }
1641  }
1642  }
1643 
1644  controlNetSelIBO_.upload(numSel * 4, &iboData[0], GL_STATIC_DRAW);
1645  }
1646  }
1647 
1648  invalidateControlNetMeshSel_ = false;
1649 }
1650 
1651 //----------------------------------------------------------------------------
1652 
1653 template <class BSplineSurfaceType>
1654 void
1657 {
1658  const size_t knotBufSizeU = bsplineSurface_.get_knots_m().size();
1659  const size_t knotBufSizeV = bsplineSurface_.get_knots_n().size();
1660 
1661  const size_t numControlPointsU = bsplineSurface_.n_control_points_m();
1662  const size_t numControlPointsV = bsplineSurface_.n_control_points_n();
1663 
1664 
1665  if (knotBufSizeU)
1666  {
1667  std::vector<float> knotBufU(knotBufSizeU);
1668 
1669  for (size_t i = 0; i < knotBufSizeU; ++i)
1670  knotBufU[i] = float(bsplineSurface_.get_knot_m(i));
1671 
1672  knotTexBufferU_.setBufferData(knotBufSizeU * 4, &knotBufU[0], GL_R32F);
1673  }
1674 
1675  if (knotBufSizeV)
1676  {
1677  std::vector<float> knotBufV(knotBufSizeV);
1678 
1679  for (size_t i = 0; i < knotBufSizeV; ++i)
1680  knotBufV[i] = float(bsplineSurface_.get_knot_n(i));
1681 
1682  knotTexBufferV_.setBufferData(knotBufSizeV * 4, &knotBufV[0], GL_R32F);
1683  }
1684 
1685 
1686 #ifdef GL_VERSION_3_0
1687 
1688  const size_t controlPointBufSize = numControlPointsU * numControlPointsV;
1689 
1690  if (controlPointBufSize)
1691  {
1692  std::vector<float> controlPointBuf(controlPointBufSize * 3);
1693 
1694  for (size_t y = 0; y < numControlPointsV; ++y)
1695  {
1696  for (size_t x = 0; x < numControlPointsU; ++x)
1697  {
1698  Point cp = bsplineSurface_.get_control_point(x, y);
1699  controlPointBuf[(y * numControlPointsU + x) * 3 + 0] = cp[0];
1700  controlPointBuf[(y * numControlPointsU + x) * 3 + 1] = cp[1];
1701  controlPointBuf[(y * numControlPointsU + x) * 3 + 2] = cp[2];
1702  }
1703  }
1704 
1705  controlPointTex_.bind();
1706  controlPointTex_.parameter(GL_TEXTURE_MIN_FILTER, GL_NEAREST); // disable filtering
1707  controlPointTex_.parameter(GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1708  controlPointTex_.setData(0, GL_RGB32F, numControlPointsU, numControlPointsV, GL_RGB, GL_FLOAT, &controlPointBuf[0]);
1709  }
1710 #endif
1711 }
1712 
1713 
1714 //=============================================================================
1715 } // namespace SceneGraph
1716 } // namespace ACG
1717 //=============================================================================
VectorT< float, 2 > Vec2f
Definition: VectorT.hh:108
static void bindTexture(GLenum _target, GLuint _buffer)
replaces glBindTexture, supports locking
unsigned int pick_current_index() const
Returns the current color picking index (can be used for caching)
Definition: GLState.cc:1114
void pick_create_texture(GLState &_state)
create texture image
const Vec4f & clear_color() const
get background color
Definition: GLState.hh:924
Vec3d eye() const
get eye point
Definition: GLState.cc:882
DrawMode SOLID_SMOOTH_SHADED
draw smooth shaded (Gouraud shaded) faces (requires halfedge normals)
Definition: DrawModes.cc:88
void addTexture(const Texture &_t)
adds a texture to stage RenderObjects::numTextures()
void glColor(const Vec3f &_v)
Wrapper: glColor for Vec3f.
Definition: gl.hh:146
void updateTexBuffers()
update texture resources for gpu-based spline evaluation
DrawMode HIDDENLINE
draw hidden line (2 rendering passes needed)
Definition: DrawModes.cc:86
DrawMode SOLID_FLAT_SHADED
draw flat shaded faces (requires face normals)
Definition: DrawModes.cc:87
DrawModeProperties stores a set of properties that defines, how to render an object.
Definition: DrawModes.hh:183
VectorT< float, 4 > Vec4f
Definition: VectorT.hh:144
void setupShaderGenFromDrawmode(const SceneGraph::DrawModes::DrawModeProperties *_props)
Fills out ShaderGenDesc parameters based on Drawmode properties.
DrawMode WIREFRAME
draw wireframe
Definition: DrawModes.cc:84
void push_modelview_matrix()
push modelview matrix
Definition: GLState.cc:1006
void create_knot_selection_texture(GLState &_state)
creates texture to put onto nurbs curve for visualization of knotvector selection ...
bool textured() const
Is texturing enabled?
Definition: DrawModes.hh:225
GLuint indexBuffer
Use vertex array object.
defined by user via VertexElement::shaderInputName_
const VertexDeclaration * vertexDecl
Defines the vertex buffer layout, ignored if VAO is provided.
Vec4uc pick_get_name_color(unsigned int _idx)
Definition: GLState.cc:1064
void getRenderObjects(IRenderer *_renderer, GLState &_state, const DrawModes::DrawMode &_drawMode, const Material *_mat)
create render objects
void pick(GLState &_state, PickTarget _target)
picking
int viewport_width() const
get viewport width
Definition: GLState.hh:825
void set_arb_texture(const QImage &_texture, bool _repeat=false, float _u_repeat=1.0f, float _v_repeat=1.0f)
use arbitrary texture (in SOLID_TEXTURED mode)
unsigned int patchVertices
patch size if primitiveMode is GL_PATCHES for rendering with tessellation shaders ...
void selection_init_texturing(GLuint &_texture_idx)
generate index and setup texture parameters for selection visualization
DrawMode POINTS
draw unlighted points using the default base color
Definition: DrawModes.cc:79
Vec3d project(const Vec3d &_point) const
project point in world coordinates to window coordinates
Definition: GLState.cc:638
PickTarget
What target to use for picking.
Definition: BaseNode.hh:99
bool openGLVersion(const int _major, const int _minor)
Definition: gl.cc:95
size_t getNumLayers() const
returns the layer count
vector_type & maximize(const vector_type &_rhs)
maximize values: same as *this = max(*this, _rhs), but faster
Definition: Vector11T.hh:562
static void enable(GLenum _cap)
replaces glEnable, but supports locking
const GLenum & depthFunc() const
get glDepthFunc() that is supposed to be active
Definition: GLState.cc:937
DrawMode SOLID_TEXTURED
draw textured faces
Definition: DrawModes.cc:94
VectorT< float, 3 > Vec3f
Definition: VectorT.hh:125
const Vec4f & base_color() const
get base color (used when lighting is off)
Definition: GLState.hh:929
float point_size() const
get point size
Definition: GLState.hh:973
Texture to be used.
void draw(GLState &_state, const DrawModes::DrawMode &_drawMode)
draw lines and normals
DrawModes::DrawMode availableDrawModes() const
return available draw modes
void translate(double _x, double _y, double _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
translate by (_x, _y, _z)
Definition: GLState.cc:531
virtual void addRenderObject(RenderObject *_renderObject)
Callback for the scenegraph nodes, which send new render objects via this function.
Definition: IRenderer.cc:108
void resetPointRendering()
Reset shader template names blocked by point rendering.
DrawMode SOLID_PHONG_SHADED
draw phong shaded faces
Definition: DrawModes.cc:89
bool pick_set_maximum(unsigned int _idx)
Set the maximal number of primitives/components of your object.
Definition: GLState.cc:1047
void setupPointRendering(float _pointSize, const Vec2f &_screenSize)
Setup rendering of circle points.
void setUniform(const char *_name, GLint _value)
set values for int uniforms
std::string name
Name for logging.
const DrawModeProperties * getLayer(unsigned int _i) const
returns the property set at layer i
static void depthRange(GLclampd _zNear, GLclampd _zFar)
replaces glDepthRange, supports locking
static void disable(GLenum _cap)
replaces glDisable, but supports locking
Namespace providing different geometric functions concerning angles.
Definition: DBSCANT.cc:51
picks verices (may not be implemented for all nodes)
Definition: BaseNode.hh:108
Pick spline curve or surface (picks u or u,v coords respectively)
Definition: BaseNode.hh:118
void setupLineRendering(float _lineWidth, const Vec2f &_screenSize)
Setup rendering of thick lines.
void pop_modelview_matrix()
pop modelview matrix
Definition: GLState.cc:1022
void pick_set_name(unsigned int _idx)
sets the current name/color (like glLoadName(_idx))
Definition: GLState.cc:1057
void rotate(double _angle, double _x, double _y, double _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
rotate around axis (_x, _y, _z) by _angle
Definition: GLState.cc:562
DrawMode SOLID_ENV_MAPPED
draw environment mapped
Definition: DrawModes.cc:93
auto normalize() -> decltype(*this/=std::declval< VectorT< S, DIM >>().norm())
Definition: Vector11T.hh:428
DrawMode SOLID_1DTEXTURED
draw textured faces
Definition: DrawModes.cc:96
void updateSurfaceMesh(int _vertexCountU=50, int _vertexCountV=50)
update vertex + index buffer of surface mesh
void initFromState(GLState *_glState)
Initializes a RenderObject instance.
Definition: RenderObject.cc:69
void boundingBox(Vec3d &_bbMin, Vec3d &_bbMax)
update bounding box
void set_base_color(const Vec4f &_col)
set base color (used when lighting is off)
Definition: GLState.cc:675
pick any of the prior targets (should be implemented for all nodes)
Definition: BaseNode.hh:110
vector_type & minimize(const vector_type &_rhs)
minimize values: same as *this = min(*this, _rhs), but faster
Definition: Vector11T.hh:534
int viewport_height() const
get viewport height
Definition: GLState.hh:827
float line_width() const
get line width
Definition: GLState.hh:978
void updateControlNetMeshSel()
update index buffer of selected control points
Interface class between scenegraph and renderer.
void pick_init_texturing()
generate index and setup texture parameters
VectorT< double, 3 > Vec3d
Definition: VectorT.hh:127
picks faces (should be implemented for all nodes)
Definition: BaseNode.hh:104
GLuint vertexBuffer
VBO, IBO ids, ignored if VAO is provided.
void updateControlNetMesh()
update vertex + index buffer of control net mesh
ShaderGenDesc shaderDesc
Drawmode and other shader params.
void updateGeometry()
update vertex buffer for rendering
void create_cp_selection_texture(GLState &_state)
creates texture to put onto nurbs curve for visualization of control point selection ...
static void shadeModel(GLenum _mode)
replaces glShadeModel, supports locking
const GLenum & depthFunc() const
get glDepthFunc() that is supposed to be active
Vec3d viewing_direction() const
get viewing ray
Definition: GLState.hh:851