Developer Documentation
Loading...
Searching...
No Matches
LineNode.cc
1/*===========================================================================*\
2 * *
3 * OpenFlipper *
4 * Copyright (c) 2001-2015, RWTH-Aachen University *
5 * Department of Computer Graphics and Multimedia *
6 * All rights reserved. *
7 * www.openflipper.org *
8 * *
9 *---------------------------------------------------------------------------*
10 * This file is part of OpenFlipper. *
11 *---------------------------------------------------------------------------*
12 * *
13 * Redistribution and use in source and binary forms, with or without *
14 * modification, are permitted provided that the following conditions *
15 * are met: *
16 * *
17 * 1. Redistributions of source code must retain the above copyright notice, *
18 * this list of conditions and the following disclaimer. *
19 * *
20 * 2. Redistributions in binary form must reproduce the above copyright *
21 * notice, this list of conditions and the following disclaimer in the *
22 * documentation and/or other materials provided with the distribution. *
23 * *
24 * 3. Neither the name of the copyright holder nor the names of its *
25 * contributors may be used to endorse or promote products derived from *
26 * this software without specific prior written permission. *
27 * *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40\*===========================================================================*/
41
42
43
44
45
46
47//=============================================================================
48//
49// CLASS LineNode - IMPLEMENTATION
50//
51//=============================================================================
52
53//== INCLUDES =================================================================
54#include <ACG/GL/acg_glew.hh>
55#include "LineNode.hh"
56#include <ACG/GL/IRenderer.hh>
57
58//== NAMESPACES ===============================================================
59
60namespace ACG {
61namespace SceneGraph {
62
63//== IMPLEMENTATION ==========================================================
64
66 BaseNode* _parent,
67 std::string _name ) :
68 MaterialNode(_parent, _name, MaterialNode::BaseColor | MaterialNode::LineWidth),
69 picking_line_width_(std::numeric_limits<float>::infinity()),
70 line_mode_(_mode),
71 draw_always_on_top (false),
72 prev_depth_(GL_LESS),
73 vbo_(0),
74 updateVBO_(true),
75 lineNodeName_("")
76{
78}
79
80//----------------------------------------------------------------------------
81
83 if (vbo_)
84 glDeleteBuffers(1, &vbo_);
85
86}
87
88//----------------------------------------------------------------------------
89
91{
92 // Set the new line mode
93 line_mode_ = _mode;
94
95 // Force an update of the vbo
96 updateVBO_ = true;
97}
98
99//----------------------------------------------------------------------------
100
102{
103 clear_points();
104 clear_colors();
105}
106
107//----------------------------------------------------------------------------
108
110{
111 points_.clear();
112
113 // Force an update of the vbo
114 updateVBO_ = true;
115}
116
117//----------------------------------------------------------------------------
118
120{
121 colors_.clear();
122 colors4f_.clear();
123
124 // Force an update of the vbo
125 updateVBO_ = true;
126}
127
128//----------------------------------------------------------------------------
129
131{
132 clear_colors();
133 add_color(ACG::Vec3uc((char) (((int) _c[0]) * 255),
134 (char) (((int) _c[1]) * 255),
135 (char) (((int) _c[2]) * 255)));
137}
138
139//----------------------------------------------------------------------------
140
142{
143 points_.push_back(_v);
144
145 // Force an update of the vbo
146 updateVBO_ = true;
147}
148
149//----------------------------------------------------------------------------
150
151void LineNode::add_line(const Vec3d& _v0, const Vec3d& _v1)
152{
153 add_point(_v0);
154 add_point(_v1);
155
156 // Force an update of the vbo
157 updateVBO_ = true;
158}
159
160//----------------------------------------------------------------------------
161
163{
164 colors_.push_back(_c);
165
166 // Force an update of the vbo
167 updateVBO_ = true;
168}
169
170//----------------------------------------------------------------------------
171
173{
174 colors4f_.push_back(_c);
175
176 // Force an update of the vbo
177 updateVBO_ = true;
178}
179
180//----------------------------------------------------------------------------
181
182void
184boundingBox(Vec3d& _bbMin, Vec3d& _bbMax)
185{
186 ConstPointIter p_it=points_.begin(), p_end=points_.end();
187 for (; p_it!=p_end; ++p_it)
188 {
189 _bbMax.maximize(*p_it);
190 _bbMin.minimize(*p_it);
191 }
192}
193
194
195//----------------------------------------------------------------------------
196
197
200availableDrawModes() const
201{
203}
204
205
206//----------------------------------------------------------------------------
207
208void
210enter(GLState& _state , const DrawModes::DrawMode& _drawMode)
211{
212 MaterialNode::enter(_state, _drawMode);
213
214 if (alwaysOnTop()) {
215 //store current depth comparison function (needed for lasso selection)
216 prev_depth_ = _state.depthFunc();
217
218 //set depth function and change GLState accordingly
219 _state.set_depthFunc(GL_ALWAYS);
220 }
221}
222
223//----------------------------------------------------------------------------
224
225void
227draw(GLState& _state , const DrawModes::DrawMode& _drawMode)
228{
229 if(_state.compatibilityProfile())
230 drawCompat(_state, _drawMode);
231 else
232 {
233 /* //Node Based Drawing is not supported on Core profiles
234 if (_drawMode & DrawModes::WIREFRAME)
235 {
236 ACG::GLState::disable(GL_LIGHTING);
237
238
239 // if (line_mode_ == LineSegmentsMode)
240 // glBegin(GL_LINES);
241 // else
242 // glBegin(GL_LINE_STRIP);
243
244
245 if (line_mode_ == LineSegmentsMode)
246 {
247 // first check if (new standard) 4-channel colors are specified
248 if( (points_.size()/2 == colors4f_.size()) )
249 {
250 // enable blending of lines
251 GLboolean blendb;
252 glGetBooleanv( GL_BLEND, &blendb);
253 glEnable(GL_BLEND);
254 // blend ontop of prev. drawn mesh
255 GLboolean depthmaskb;
256 glGetBooleanv( GL_DEPTH_WRITEMASK, &depthmaskb);
257 glDepthMask(GL_FALSE);
258
259 glBegin(GL_LINES);
260
261 ConstPointIter p_it=points_.begin(), p_end=points_.end();
262 ConstColor4fIter c_it=colors4f_.begin();
263
264 Color4f c(1.0f,1.0f,1.0f,1.0f);
265 if(c_it != colors4f_.end()) {
266 c = *c_it;
267 }
268
269 int cnt = 0;
270 for (; p_it!=p_end; ++p_it)
271 {
272 if ((cnt > 0) && (cnt % 2 == 0) && (c_it+1) != colors4f_.end()) {
273 ++c_it;
274 c = *c_it;
275 }
276
277 glColor(c);
278 glVertex(*p_it);
279
280 ++cnt;
281 }
282
283 glEnd();
284
285 // disable blending of lines
286 if( blendb == GL_FALSE )
287 glDisable(GL_BLEND);
288
289 // enable depth mask
290 if( depthmaskb == GL_TRUE )
291 glDepthMask(GL_TRUE);
292
293 }
294 else if ((line_mode_ == LineSegmentsMode) && (points_.size()/2 == colors_.size()) )
295 {
296 glBegin(GL_LINES);
297 ConstPointIter p_it=points_.begin(), p_end=points_.end();
298 ConstColorIter c_it=colors_.begin();
299
300 Color c((char)255, (char)255, (char)255);
301 if(c_it != colors_.end()) {
302 c = *c_it;
303 }
304
305 int cnt = 0;
306 for (; p_it!=p_end; ++p_it)
307 {
308 if ((cnt > 0) && (cnt % 2 == 0) && (c_it+1) != colors_.end()) {
309 ++c_it;
310 c = *c_it;
311 }
312
313 glColor(c);
314 glVertex(*p_it);
315
316 ++cnt;
317 }
318 glEnd();
319 }
320 else
321 {
322 glBegin(GL_LINES);
323
324 ConstPointIter p_it=points_.begin(), p_end=points_.end();
325
326 for (; p_it!=p_end; ++p_it)
327 {
328 glVertex(*p_it);
329 }
330
331 glEnd();
332 }
333 }
334 else
335 {
336 _state.set_color(_state.base_color());
337 glBegin(GL_LINE_STRIP);
338 ConstPointIter p_it=points_.begin(), p_end=points_.end();
339 for (; p_it!=p_end; ++p_it)
340 glVertex(*p_it);
341 glEnd();
342 }
343
344 //glEnd();
345 }*/
346 }
347}
348
349//----------------------------------------------------------------------------
350
351void
353leave(GLState& _state , const DrawModes::DrawMode& _drawMode)
354{
355 if (alwaysOnTop()) {
356 //restore depth function and change GLState accordingly
357 _state.set_depthFunc(prev_depth_);
358 }
359
360 MaterialNode::leave(_state, _drawMode);
361}
362
363//----------------------------------------------------------------------------
364
365void LineNode::pick(GLState& _state , PickTarget _target)
366{
367 if(_state.compatibilityProfile())
368 pickCompat(_state, _target);
369 else
370 {
371 if (n_points() == 0)
372 return;
373
374 // Bind the vertex array
375 ACG::GLState::bindBuffer(GL_ARRAY_BUFFER_ARB, 0);
376
377 const size_t n_edges = n_points() - 1;
378
379 switch (_target)
380 {
381 case PICK_EDGE:
382 {
383 _state.pick_set_maximum (n_edges);
384 pick_edges(_state, 0);
385 break;
386 }
387
388 case PICK_ANYTHING:
389 {
390 _state.pick_set_maximum (n_edges);
391 pick_edges(_state, 0);
392 break;
393 }
394
395 default:
396 break;
397 }
398 }
399}
400
401//----------------------------------------------------------------------------
402
403void LineNode::pick_edges(GLState& _state, unsigned int _offset)
404{
405 //TODO: implement edge picking for lines in CoreProfile
406}
407
408//----------------------------------------------------------------------------
409
411{
412 if (!updateVBO_)
413 return;
414
415 // create vbo if it does not exist
416 if (!vbo_)
417 glGenBuffers(1, &vbo_);
418
419 vertexDecl_.clear();
420 vertexDecl_.addElement(GL_FLOAT, 3, VERTEX_USAGE_POSITION);
421
422 //3 coordinates per vertex
423 std::vector<float> vboData(3*points_.size(),0.f);
424
425 if (line_mode_ == LineSegmentsMode)
426 {
427 if( (points_.size()/2 == colors4f_.size()) )
428 {
429 // === One color entry per line segment (alpha channel available ) ===
430 vertexDecl_.addElement(GL_FLOAT, 4, VERTEX_USAGE_COLOR);
431 vboData.resize(vboData.size() + 4 * points_.size());
432 float* vboPtr = &vboData[0];
433
434 ConstPointIter p_it=points_.begin(), p_end=points_.end();
435 ConstColor4fIter c_it=colors4f_.begin();
436
437 Color4f c(1.0f,1.0f,1.0f,1.0f);
438 if(c_it != colors4f_.end()) {
439 c = *c_it;
440 }
441
442 int cnt = 0;
443 for (; p_it!=p_end; ++p_it)
444 {
445 if ((cnt > 0) && (cnt % 2 == 0) && (c_it+1) != colors4f_.end()) {
446 ++c_it;
447 c = *c_it;
448 }
449 //add position information
450 *(vboPtr++) = (*p_it)[0];
451 *(vboPtr++) = (*p_it)[1];
452 *(vboPtr++) = (*p_it)[2];
453
454 //add color information
455 *(vboPtr++) = c[0];
456 *(vboPtr++) = c[1];
457 *(vboPtr++) = c[2];
458 *(vboPtr++) = c[3];
459
460 ++cnt;
461 }
462
463 //====================
464 } else if ( points_.size()/2 == colors_.size() )
465 {
466 //=== One color entry per line segment (no alpha channel available and uchars as colors) ===
467 vertexDecl_.addElement(GL_FLOAT, 4, VERTEX_USAGE_COLOR);
468 //add 4 colors for each vertex
469 vboData.resize(vboData.size() + 4 * points_.size());
470 float* vboPtr = &vboData[0];
471
472 ConstPointIter p_it=points_.begin(), p_end=points_.end();
473 ConstColorIter c_it=colors_.begin();
474
475 Color c((char)255, (char)255, (char)255);
476 if(c_it != colors_.end()) {
477 c = *c_it;
478 }
479
480 int cnt = 0;
481 for (; p_it!=p_end; ++p_it)
482 {
483 if ((cnt > 0) && (cnt % 2 == 0) && (c_it+1) != colors_.end()) {
484 ++c_it;
485 c = *c_it;
486 }
487
488 //add position information
489 *(vboPtr++) = (*p_it)[0];
490 *(vboPtr++) = (*p_it)[1];
491 *(vboPtr++) = (*p_it)[2];
492
493 //add color information
494 *(vboPtr++) = c[0]/255.f;
495 *(vboPtr++) = c[1]/255.f;
496 *(vboPtr++) = c[2]/255.f;
497 *(vboPtr++) = 1.f;
498
499 ++cnt;
500 }
501
502 //===========
503 } else
504 {
505 //=== No colors. Just draw the segments ===
506 ConstPointIter p_it=points_.begin(), p_end=points_.end();
507 float* vboPtr = &vboData[0];
508
509 for (; p_it!=p_end; ++p_it)
510 {
511 *(vboPtr++) = (*p_it)[0];
512 *(vboPtr++) = (*p_it)[1];
513 *(vboPtr++) = (*p_it)[2];
514 }
515 //===========
516 }
517
518
519 }
520 else
521 {
522 // === No colors (Use material) and one continuous line ===
523 // Pointer to it for easier copy operation
524 float* pPoints = &vboData[0];
525
526 // Copy from internal storage to vbo in memory
527 for (unsigned int i = 0 ; i < points_.size(); ++i) {
528 for ( unsigned int j = 0 ; j < 3 ; ++j) {
529 *(pPoints++) = points_[i][j];
530 }
531 }
532 }
533
534 glBindBuffer(GL_ARRAY_BUFFER_ARB, vbo_);
535 glBufferData(GL_ARRAY_BUFFER_ARB, vboData.size()*sizeof(float) , &vboData[0] , GL_STATIC_DRAW_ARB);
536
537 // Update done.
538 updateVBO_ = false;
539
540}
541
542void
544getRenderObjects(IRenderer* _renderer, GLState& _state , const DrawModes::DrawMode& _drawMode , const ACG::SceneGraph::Material* _mat) {
545
546 if (points_.empty())
547 return;
548
549 // init base render object
550
551 RenderObject ro;
552 ro.initFromState(&_state);
553 ro.setMaterial(_mat);
554
555 lineNodeName_ = std::string("LineNode: ")+name();
556 ro.debugName = lineNodeName_;
557
558 // draw after scene-meshes
559 if (draw_always_on_top)
560 {
561 ro.priority = 1;
562 ro.depthTest = false;
563 ro.depthWrite = false;
564 }
565 else
566 {
567 ro.depthTest = true;
568 ro.depthWrite = true;
569 }
570
571 //set blending
572 if ((line_mode_ == LineSegmentsMode) && (points_.size()/2 == colors4f_.size()))
573 {
574 ro.blending = true;
575 ro.blendSrc = GL_SRC_ALPHA;
576 ro.blendDest = GL_ONE_MINUS_SRC_ALPHA;
577 }
578
579 // simulate line width via quad extrusion in geometry shader
580 QString geomTemplate = ShaderProgGenerator::getShaderDir();
581 geomTemplate += "Wireframe/geom_line2quad.tpl";
582
583 ro.shaderDesc.geometryTemplateFile = geomTemplate;
584
585 ro.setUniform("screenSize", Vec2f((float)_state.viewport_width(), (float)_state.viewport_height()));
586 ro.setUniform("lineWidth", _state.line_width());
587
588 createVBO();
589 ro.vertexBuffer = vbo_;
590 // vertexDecl is defined in createVBO
591 ro.vertexDecl = &vertexDecl_;
592
593 //besides of the position, colors are saved so we can show them
594 if (vertexDecl_.getNumElements() > 1)
595 ro.shaderDesc.vertexColors = true;
596
597
598 if (line_mode_ == LineSegmentsMode)
599 ro.glDrawArrays(GL_LINES, 0, int( points_.size() ));
600 else
601 ro.glDrawArrays(GL_LINE_STRIP, 0, int(points_.size()) );
602
603 _renderer->addRenderObject(&ro);
604
605}
606
607//=============================================================================
608} // namespace SceneGraph
609} // namespace ACG
610//=============================================================================
void set_depthFunc(const GLenum &_depth_func)
Call glDepthFunc() to actually change the depth comparison function, and store the new value in this ...
Definition GLState.cc:948
int viewport_width() const
get viewport width
Definition GLState.hh:847
bool pick_set_maximum(size_t _idx)
Set the maximal number of primitives/components of your object.
Definition GLState.cc:1051
int viewport_height() const
get viewport height
Definition GLState.hh:849
float line_width() const
get line width
Definition GLState.hh:1000
const GLenum & depthFunc() const
get glDepthFunc() that is supposed to be active
Definition GLState.cc:941
static void bindBuffer(GLenum _target, GLuint _buffer)
replaces glBindBuffer, supports locking
Definition GLState.cc:1820
virtual void addRenderObject(RenderObject *_renderObject)
Callback for the scenegraph nodes, which send new render objects via this function.
Definition IRenderer.cc:104
DrawModes::DrawMode drawMode() const
Return the own draw modes of this node.
Definition BaseNode.hh:430
std::string name() const
Returns: name of node (needs not be unique)
Definition BaseNode.hh:415
LineMode
Line mode: draw line segments (every 2 points) or ONE polyline.
Definition LineNode.hh:102
void add_line(const Vec3d &_v0, const Vec3d &_v1)
add line (for LineMode == LineSegmentsMode)
Definition LineNode.cc:151
void pick(GLState &_state, PickTarget _target) override
Draw the line using the GL picking name stack.
Definition LineNode.cc:365
void createVBO()
creates the vbo only if update was requested
Definition LineNode.cc:410
bool & alwaysOnTop()
get and set always on top
Definition LineNode.hh:198
void draw(GLState &_state, const DrawModes::DrawMode &_drawMode) override
draw lines and normals
Definition LineNode.cc:227
void add_color(const ACG::Vec3uc &_c)
add color (only for LineMode == LineSegmentsMode)
Definition LineNode.cc:162
LineNode(LineMode _mode, BaseNode *_parent=0, std::string _name="<LineNode>")
default constructor
Definition LineNode.cc:65
void enter(GLState &_state, const DrawModes::DrawMode &_drawMode) override
set depth function (needed for lasso selection so that the line can be draw in pseudo-2D)
Definition LineNode.cc:210
void set_color(const Vec4f &_c)
Override material node's set color function in order to locally add color.
Definition LineNode.cc:130
DrawModes::DrawMode availableDrawModes() const override
return available draw modes
Definition LineNode.cc:200
void clear()
clear points/lines and colors
Definition LineNode.cc:101
void add_point(const Vec3d &_v)
add point (for LineMode == PolygonMode)
Definition LineNode.cc:141
void clear_colors()
clear colors
Definition LineNode.cc:119
size_t n_points() const
number of points
Definition LineNode.hh:181
void set_line_mode(LineMode _mode)
set line mode (see LineNode::LineMode)
Definition LineNode.cc:90
void getRenderObjects(IRenderer *_renderer, GLState &_state, const DrawModes::DrawMode &_drawMode, const ACG::SceneGraph::Material *_mat) override
Add the objects to the given renderer.
Definition LineNode.cc:544
void clear_points()
clear points/lines
Definition LineNode.cc:109
void leave(GLState &_state, const DrawModes::DrawMode &_drawMode) override
reset depth function to what it was before enter()
Definition LineNode.cc:353
void boundingBox(Vec3d &_bbMin, Vec3d &_bbMax) override
update bounding box
Definition LineNode.cc:184
void set_color(const Vec4f &_c)
set color (base, ambient, diffuse, specular) based on _c
void enter(GLState &_state, const DrawModes::DrawMode &_drawmode) override
set current GL-color and GL-material
void leave(GLState &_state, const DrawModes::DrawMode &_drawmode) override
restores original GL-color and GL-material
void addElement(const VertexElement *_pElement)
unsigned int getNumElements() const
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
DrawMode WIREFRAME
draw wireframe
Definition DrawModes.cc:78
PickTarget
What target to use for picking.
Definition PickTarget.hh:74
@ PICK_EDGE
picks edges (may not be implemented for all nodes)
Definition PickTarget.hh:80
@ PICK_ANYTHING
pick any of the prior targets (should be implemented for all nodes)
Definition PickTarget.hh:84
Namespace providing different geometric functions concerning angles.
VectorT< float, 2 > Vec2f
Definition VectorT.hh:102
@ VERTEX_USAGE_COLOR
"inColor"
@ VERTEX_USAGE_POSITION
"inPosition"
Interface class between scenegraph and renderer.
ShaderGenDesc shaderDesc
Drawmode and other shader params.
const VertexDeclaration * vertexDecl
Defines the vertex buffer layout, ignored if VAO is provided.
int priority
Priority to allow sorting of objects.
GLuint vertexBuffer
VBO, IBO ids, ignored if VAO is provided.
void setUniform(const char *_name, GLint _value)
set values for int uniforms
GLenum blendDest
glBlendFunc: GL_SRC_ALPHA, GL_ZERO, GL_ONE, GL_ONE_MINUS_SRC_ALPHA ...
void initFromState(GLState *_glState)
Initializes a RenderObject instance.