Developer Documentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
PlaneNode.cc
1 /*===========================================================================*\
2  * *
3  * OpenFlipper *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openflipper.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenFlipper. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39  * *
40 \*===========================================================================*/
41 
42 /*===========================================================================*\
43  * *
44  * $Revision$ *
45  * $Author$ *
46  * $Date$ *
47  * *
48 \*===========================================================================*/
49 
50 #include <ACG/GL/acg_glew.hh>
51 
52 #include "PlaneNode.hh"
53 
54 //== IMPLEMENTATION ==========================================================
55 
56 
57 PlaneNode::PlaneNode(Plane& _plane, BaseNode *_parent, std::string _name)
58 :BaseNode(_parent, _name),
59  plane_(_plane),
60  vbo_(0),
61  vboNeedsUpdate_(true),//not initialized, so we need an update
62  sphere_(0)
63 
64 {
65  vertexDecl_.addElement(GL_FLOAT, 3, ACG::VERTEX_USAGE_POSITION);
66  vertexDecl_.addElement(GL_FLOAT, 3, ACG::VERTEX_USAGE_NORMAL);
67 
68  sphere_ = new ACG::GLSphere(10, 10);
69  setPlane(_plane);
70 }
71 
73 {
74  if ( vbo_)
75  glDeleteBuffers(1,&vbo_);
76 
77 }
78 
80 {
81 
82  ACG::Vec3d pos = plane_.position - plane_.xDirection * 0.5 - plane_.yDirection * 0.5;
83 
84  //add a little offset in normal direction
85  ACG::Vec3d pos0 = ACG::Vec3d( pos + plane_.normal * 0.1 );
86  ACG::Vec3d pos1 = ACG::Vec3d( pos - plane_.normal * 0.1 );
87 
88  ACG::Vec3d xDird = ACG::Vec3d( plane_.xDirection );
89  ACG::Vec3d yDird = ACG::Vec3d( plane_.yDirection );
90 
91  _bbMin.minimize( pos0 );
92  _bbMin.minimize( pos0 + xDird);
93  _bbMin.minimize( pos0 + yDird);
94  _bbMin.minimize( pos0 + xDird + yDird);
95  _bbMax.maximize( pos1 );
96  _bbMax.maximize( pos1 + xDird);
97  _bbMax.maximize( pos1 + yDird);
98  _bbMax.maximize( pos1 + xDird + yDird);
99 
100  _bbMin.minimize( pos1 );
101  _bbMin.minimize( pos1 + xDird);
102  _bbMin.minimize( pos1 + yDird);
103  _bbMin.minimize( pos1 + xDird + yDird);
104  _bbMax.maximize( pos0 );
105  _bbMax.maximize( pos0 + xDird);
106  _bbMax.maximize( pos0 + yDird);
107  _bbMax.maximize( pos0 + xDird + yDird);
108 
109 }
110 
111 //----------------------------------------------------------------------------
112 
115 {
118 }
119 
120 //----------------------------------------------------------------------------
121 
122 
123 
124 //----------------------------------------------------------------------------
125 
126 void PlaneNode::drawPlane( ACG::GLState& _state) {
127 
128  const ACG::Vec3d xy = plane_.xDirection + plane_.yDirection;
129 
130  // Array of coordinates for the plane
131  float vboData_[9 * 3 ] = { 0.0,0.0,0.0,
132  (float)plane_.xDirection[0],(float)plane_.xDirection[1],(float)plane_.xDirection[2],
133  (float)xy[0],(float)xy[1],(float)xy[2],
134  (float)plane_.yDirection[0],(float)plane_.yDirection[1],(float)plane_.yDirection[2],
135  0.0,0.0,0.0,
136  (float)plane_.yDirection[0],(float)plane_.yDirection[1],(float)plane_.yDirection[2],
137  (float)xy[0],(float)xy[1],(float)xy[2],
138  (float)plane_.xDirection[0],(float)plane_.xDirection[1],(float)plane_.xDirection[2],
139  0.0,0.0,0.0 };
140 
141  // Enable the arrays
142  _state.enableClientState(GL_VERTEX_ARRAY);
143  _state.vertexPointer(3,GL_FLOAT,0,&vboData_[0]);
144 
145  //first draw the lines
146  _state.set_color(ACG::Vec4f(1.0, 1.0, 1.0 , 1.0) );
147  glLineWidth(2.0);
148 
149  glDrawArrays(GL_LINE_STRIP,0,5);
150 
151  glLineWidth(1.0);
152 
153  // Remember blending state
154  bool blending = _state.blending();
155  bool culling = _state.isStateEnabled(GL_CULL_FACE);
156 
157  //then the red front side
158  ACG::GLState::enable (GL_BLEND);
159  ACG::GLState::blendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
160 
161  ACG::GLState::enable (GL_CULL_FACE);
162 
163  _state.set_color(ACG::Vec4f( 0.6f, 0.15f, 0.2f, 0.5f));
164  glDrawArrays(GL_QUADS,0,4);
165 
166 
167  //finally the green back side
168  _state.set_color(ACG::Vec4f(0.1f, 0.8f, 0.2f, 0.5f ));
169 
170  glDrawArrays(GL_QUADS,5,4);
171 
172  if ( !blending )
173  ACG::GLState::disable(GL_BLEND);
174 
175  if ( !culling )
176  ACG::GLState::disable(GL_CULL_FACE);
177 
178  // deactivate vertex arrays after drawing
179  _state.disableClientState(GL_VERTEX_ARRAY);
180 
181 }
182 
183 //----------------------------------------------------------------
184 
185 void PlaneNode::drawPlanePick( ACG::GLState& _state) {
186 
187  _state.pick_set_maximum(1);
188  _state.pick_set_name(0);
189 
190  const ACG::Vec3d xy = plane_.xDirection + plane_.yDirection;
191 
192  // Array of coordinates for the plane
193  float vboData_[4* 3 ] = { 0.0,0.0,0.0,
194  (float)plane_.xDirection[0],(float)plane_.xDirection[1],(float)plane_.xDirection[2],
195  (float)xy[0],(float)xy[1],(float)xy[2],
196  (float)plane_.yDirection[0],(float)plane_.yDirection[1],(float)plane_.yDirection[2] };
197 
198  // Enable the arrays
199  _state.enableClientState(GL_VERTEX_ARRAY);
200  _state.vertexPointer(3,GL_FLOAT,0,&vboData_[0]);
201 
202  glDrawArrays(GL_QUADS,0,4);
203 
204  // deactivate vertex arrays after drawing
205  _state.disableClientState(GL_VERTEX_ARRAY);
206 
207 }
208 
209 //----------------------------------------------------------------
210 
211 void PlaneNode::draw(ACG::GLState& _state , const ACG::SceneGraph::DrawModes::DrawMode& /*_drawMode*/)
212 {
213 
214  _state.push_modelview_matrix();
215  glPushAttrib(GL_COLOR_BUFFER_BIT);
216  glPushAttrib(GL_LIGHTING_BIT);
217 
218  glColorMaterial ( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE ) ;
219  ACG::GLState::enable(GL_COLOR_MATERIAL);
220 
221  // plane_.position represents the center of the plane.
222  // Compute the corner position
223  ACG::Vec3d pos = plane_.position - plane_.xDirection*0.5 - plane_.yDirection*0.5;
224 
225  // translate to corner position
226  _state.translate(pos[0], pos[1], pos[2]);
227 
228  // draw the plane
229  drawPlane(_state);
230 
231  glPopAttrib();
232  glPopAttrib();
233  _state.pop_modelview_matrix();
234 }
235 
236 
237 //----------------------------------------------------------------
238 
239 void
241 {
242  if (_target == ACG::SceneGraph::PICK_ANYTHING) {
243 
244  _state.push_modelview_matrix();
245 
246  ACG::Vec3d pos = plane_.position - plane_.xDirection*0.5 - plane_.yDirection*0.5;
247 
248  _state.translate(pos[0], pos[1], pos[2]);
249 
250  drawPlanePick(_state);
251 
252  _state.pop_modelview_matrix();
253  }
254 }
255 
256 //----------------------------------------------------------------
257 
259 {
260  return plane_.position;
261 }
262 
263 //----------------------------------------------------------------
264 
266 {
267  return plane_.normal;
268 }
269 
270 //----------------------------------------------------------------
271 
273 {
274  return plane_.xDirection;
275 }
276 
277 //----------------------------------------------------------------
278 
280 {
281  return plane_.yDirection;
282 }
283 
284 //----------------------------------------------------------------
285 
287 {
288  return plane_;
289 }
290 
291 //----------------------------------------------------------------
292 
294 {
295  plane_ = plane;
296  update();
297 }
298 
299 //----------------------------------------------------------------------------
300 
301 void
302 PlaneNode::
303 addSphereAt(ACG::Vec3d _pos, ACG::IRenderer* _renderer, ACG::GLState& _state, ACG::RenderObject* _ro) {
304  // 1. Project point to screen
305  ACG::Vec3d projected = _state.project( _pos );
306 
307  // 2. Shift it by the requested point size
308  // glPointSize defines the diameter but we want the radius, so we divide it by two
309  ACG::Vec3d shifted = projected;
310  shifted[0] = shifted[0] + (double)_state.point_size() / 2.0 ;
311 
312  // 3. un-project into 3D
313  ACG::Vec3d unProjectedShifted = _state.unproject( shifted );
314 
315  // 4. The difference vector defines the radius in 3D for the sphere
316  ACG::Vec3d difference = unProjectedShifted - _pos ;
317 
318  const double sphereSize = difference.norm();
319 
320  sphere_->addToRenderer(_renderer, _ro, sphereSize, ACG::Vec3f(_pos));
321 }
322 
324  //update the plane in the next renderstep
325  //if the old renderer is used, nothing to do here
326  //if the new, shader based renderer is used, we have to update the vbo
327  // this is done at the next render call
328 
329  //this method prevents, that the vbo is created, if we don't use a shader based renderer
330  vboNeedsUpdate_ = true;
331 }
332 
333 //----------------------------------------------------------------------------
334 
336 {
337  if (!vboNeedsUpdate_)
338  return;
339 
340  if ( !vbo_ ) {
341  glGenBuffersARB(1, &vbo_);
342  }
343 
344  const ACG::Vec3d xy = plane_.xDirection + plane_.yDirection;
345  const ACG::Vec3d normal = (plane_.xDirection % plane_.yDirection).normalized();
346 
347  // Array of coordinates for the plane ( duplicated due to front and back rendering )
348  // Interleaved with normals
349  // 8 vertices with (3 float for position + 3 float for normal)
350  const size_t vboSize = 8 * (3+3);
351  float vboData[vboSize] = { 0.0,0.0,0.0,
352  (float)normal[0],(float)normal[1],(float)normal[2],
353  (float)plane_.xDirection[0],(float)plane_.xDirection[1],(float)plane_.xDirection[2],
354  (float)normal[0],(float)normal[1],(float)normal[2],
355  (float)xy[0],(float)xy[1],(float)xy[2],
356  (float)normal[0],(float)normal[1],(float)normal[2],
357  (float)plane_.yDirection[0],(float)plane_.yDirection[1],(float)plane_.yDirection[2],
358  (float)normal[0],(float)normal[1],(float)normal[2],
359  (float)plane_.yDirection[0],(float)plane_.yDirection[1],(float)plane_.yDirection[2],
360  (float)-normal[0],(float)-normal[1],(float)-normal[2],
361  (float)xy[0],(float)xy[1],(float)xy[2],
362  (float)-normal[0],(float)-normal[1],(float)-normal[2],
363  (float)plane_.xDirection[0],(float)plane_.xDirection[1],(float)plane_.xDirection[2],
364  (float)-normal[0],(float)-normal[1],(float)-normal[2],
365  0.0,0.0,0.0,
366  (float)-normal[0],(float)-normal[1],(float)-normal[2]};
367 
368 
369  // Bind buffer
370  glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo_);
371 
372  // Upload to buffer
373  glBufferDataARB(GL_ARRAY_BUFFER_ARB, vboSize * sizeof(float), &vboData[0], GL_STATIC_DRAW_ARB);
374 
375  // Unbind
376  ACG::GLState::bindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
377 
378  // VBO is updated for the new renderer
379  vboNeedsUpdate_ = false;
380 }
381 
382 void
385 
386  // init base render object
388 
389  _state.enable(GL_COLOR_MATERIAL);
390  _state.disable(GL_LIGHTING);
391  ro.initFromState(&_state);
392 
393  // plane_.position represents the center of the plane.
394  // Compute the corner position
395  const ACG::Vec3d pos = plane_.position - plane_.xDirection*0.5 - plane_.yDirection*0.5;
396  const ACG::Vec3d xy = plane_.xDirection + plane_.yDirection;
397 
398  // translate to corner position and store that in renderer
399  _state.push_modelview_matrix();
400  _state.translate(pos[0], pos[1], pos[2]);
401  ro.modelview = _state.modelview();
402  _state.pop_modelview_matrix();
403 
404  // Render with depth test enabled
405  ro.depthTest = true;
406 
407  updateVBO();
408 
409  // Set the buffers for rendering
410  ro.vertexBuffer = vbo_;
411  ro.vertexDecl = &vertexDecl_;
412 
413 
414  for (unsigned int i = 0; i < _drawMode.getNumLayers(); ++i)
415  {
416  ACG::SceneGraph::Material localMaterial = *_mat;
417 
418  const ACG::SceneGraph::DrawModes::DrawModeProperties* props = _drawMode.getLayer(i);
419 
420 
421  ro.setupShaderGenFromDrawmode(props);
422 
423  switch (props->primitive()) {
424 
425  case ACG::SceneGraph::DrawModes::PRIMITIVE_POINT:
426 
427  ro.blending = false;
428 
429  //---------------------------------------------------
430  // No lighting!
431  // Therefore we need some emissive color
432  //---------------------------------------------------
433  localMaterial.baseColor( localMaterial.ambientColor() );
434  ro.setMaterial(&localMaterial);
435 
436  //---------------------------------------------------
437  // Simulate glPointSize(12) with a sphere
438  //---------------------------------------------------
439 
440  ro.debugName = "Plane Sphere x";
441  addSphereAt(plane_.xDirection,_renderer,_state,&ro);
442 
443  ro.debugName = "Plane Sphere y";
444  addSphereAt(plane_.yDirection,_renderer,_state,&ro);
445 
446  ro.debugName = "Plane Sphere xy";
447  addSphereAt(xy,_renderer,_state,&ro);
448 
449  ro.debugName = "Plane Sphere 0";
450  addSphereAt(ACG::Vec3d(0.0,0.0,0.0),_renderer,_state,&ro);
451 
452 
453  break;
454  default:
455 
456  ro.priority = 10;
457 
458  // Blending enabled, since we wan't some transparency
459  ro.blending = true;
460  ro.blendSrc = GL_SRC_ALPHA;
461  ro.blendDest = GL_ONE_MINUS_SRC_ALPHA;
462 
463  // Enable culling in order to avoid z-fighting artifacts
464  ro.culling = true;
465 
466  //---------------------------------------------------
467  // Just draw the quads here ( front )
468  //---------------------------------------------------
469  ro.debugName = "PlaneNode.plane_front ";
470  localMaterial.ambientColor(ACG::Vec4f(0.6f, 0.15f, 0.2f, 0.5f ));
471  localMaterial.diffuseColor(ACG::Vec4f(0.6f, 0.15f, 0.2f, 0.5f ));
472  localMaterial.specularColor(ACG::Vec4f(0.6f, 0.15f, 0.2f, 0.5f ));
473  ro.setMaterial(&localMaterial);
474  ro.glDrawArrays(GL_QUADS, 0, 4);
475  _renderer->addRenderObject(&ro);
476 
477  //---------------------------------------------------
478  // Just draw the quads here ( back )
479  //---------------------------------------------------
480  ro.debugName = "PlaneNode.plane_back";
481  localMaterial.ambientColor( ACG::Vec4f(0.1f, 0.8f, 0.2f, 0.5f ));
482  localMaterial.diffuseColor( ACG::Vec4f(0.1f, 0.8f, 0.2f, 0.5f ));
483  localMaterial.specularColor(ACG::Vec4f(0.1f, 0.8f, 0.2f, 0.5f ));
484  ro.setMaterial(&localMaterial);
485  ro.glDrawArrays(GL_QUADS, 4, 4);
486  _renderer->addRenderObject(&ro);
487 
488  break;
489  }
490 
491  }
492 
493 
494 }
495 
496 
497 //=============================================================================
ACG::Vec3d position()
get center position of the plane
Definition: PlaneNode.cc:258
static void enable(GLenum _cap)
replaces glEnable, but supports locking
Definition: GLState.cc:1490
Namespace providing different geometric functions concerning angles.
Definition: DBSCANT.cc:51
void specularColor(const Vec4f &_s)
set the specular color
PickTarget
What target to use for picking.
Definition: BaseNode.hh:99
void getRenderObjects(ACG::IRenderer *_renderer, ACG::GLState &_state, const ACG::SceneGraph::DrawModes::DrawMode &_drawMode, const ACG::SceneGraph::Material *_mat)
Add the objects to the given renderer.
Definition: PlaneNode.cc:384
pick any of the prior targets (should be implemented for all nodes)
Definition: BaseNode.hh:110
Interface class between scenegraph and renderer.
void translate(double _x, double _y, double _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
translate by (_x, _y, _z)
Definition: GLState.cc:531
Vec3d unproject(const Vec3d &_winPoint) const
unproject point in window coordinates _winPoint to world coordinates
Definition: GLState.cc:649
GLenum blendDest
glBlendFunc: GL_SRC_ALPHA, GL_ZERO, GL_ONE, GL_ONE_MINUS_SRC_ALPHA ...
void setPlane(Plane plane)
Set a new plane for rendering.
Definition: PlaneNode.cc:293
GLuint vertexBuffer
VBO, IBO ids, ignored if VAO is provided.
const DrawModeProperties * getLayer(unsigned int _i) const
returns the property set at layer i
DrawMode SOLID_FLAT_SHADED
draw flat shaded faces (requires face normals)
Definition: DrawModes.cc:87
ACG::SceneGraph::DrawModes::DrawMode availableDrawModes() const
return available draw modes
Definition: PlaneNode.cc:114
void initFromState(GLState *_glState)
Initializes a RenderObject instance.
Definition: RenderObject.cc:69
VectorT< double, 3 > Vec3d
Definition: VectorT.hh:127
const GLMatrixd & modelview() const
get modelview matrix
Definition: GLState.hh:794
void draw(ACG::GLState &_state, const ACG::SceneGraph::DrawModes::DrawMode &_drawMode)
draw Plane
Definition: PlaneNode.cc:211
void diffuseColor(const Vec4f &_d)
set the diffuse color.
void push_modelview_matrix()
push modelview matrix
Definition: GLState.cc:1006
const VertexDeclaration * vertexDecl
Defines the vertex buffer layout, ignored if VAO is provided.
size_t getNumLayers() const
returns the layer count
void update()
updates the plane before the next render call
Definition: PlaneNode.cc:323
DrawModeProperties stores a set of properties that defines, how to render an object.
Definition: DrawModes.hh:183
unsigned int vbo_
VBO used to render the plane.
Definition: PlaneNode.hh:148
~PlaneNode()
destructor
Definition: PlaneNode.cc:72
ACG::Vec3d xDirection()
local x direction (multiplied with width)
Definition: PlaneNode.cc:272
float point_size() const
get point size
Definition: GLState.hh:973
DrawMode POINTS
draw unlighted points using the default base color
Definition: DrawModes.cc:79
void boundingBox(ACG::Vec3d &_bbMin, ACG::Vec3d &_bbMax)
update bounding box
Definition: PlaneNode.cc:79
void ambientColor(const Vec4f &_a)
set the ambient color.
void pop_modelview_matrix()
pop modelview matrix
Definition: GLState.cc:1022
virtual void addRenderObject(RenderObject *_renderObject)
Callback for the scenegraph nodes, which send new render objects via this function.
Definition: IRenderer.cc:105
void baseColor(const Vec4f &_c)
set the base color
void updateVBO()
create and update VBO
Definition: PlaneNode.cc:335
ACG::Vec3d normal()
get current normal
Definition: PlaneNode.cc:265
static void disable(GLenum _cap)
replaces glDisable, but supports locking
Definition: GLState.cc:1504
void pick(ACG::GLState &_state, ACG::SceneGraph::PickTarget _target)
draw Plane for object picking
Definition: PlaneNode.cc:240
GLMatrixd modelview
Modelview transform.
PlaneNode(Plane &_plane, BaseNode *_parent=0, std::string _name="<PlaneNode>")
Construct a plane rendering node.
Definition: PlaneNode.cc:57
ACG::Vec3d yDirection()
local y direction (multiplied with height)
Definition: PlaneNode.cc:279
void setupShaderGenFromDrawmode(const SceneGraph::DrawModes::DrawModeProperties *_props)
Fills out ShaderGenDesc parameters based on Drawmode properties.
static void bindBufferARB(GLenum _target, GLuint _buffer)
same function as bindBuffer
Definition: GLState.hh:576
int priority
Priority to allow sorting of objects.
Vec3d project(const Vec3d &_point) const
project point in world coordinates to window coordinates
Definition: GLState.cc:638
void addElement(const VertexElement *_pElement)
Plane & getPlane()
Get the currently rendered plane.
Definition: PlaneNode.cc:286