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