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