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