Developer Documentation
GlutPrimitiveNode.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 GlutPrimitiveNode - IMPLEMENTATION
50 //
51 //=============================================================================
52 
53 
54 //== INCLUDES =================================================================
55 
56 #include "GlutPrimitiveNode.hh"
57 
58 #include <ACG/GL/IRenderer.hh>
59 
60 
61 //== NAMESPACES ===============================================================
62 
63 namespace ACG {
64 namespace SceneGraph {
65 
66 
67 //== IMPLEMENTATION ==========================================================
68 
69 GlutPrimitiveNode::GlutPrimitiveNode( BaseNode* _parent,
70  const std::string & _name )
71  : BaseNode(_parent, _name),
72  setColor_(true)
73 {
74  const int slices = 20;
75  const int stacks = 20;
76 
77  sphere_ = new ACG::GLSphere(slices,stacks);
78 };
79 
80 //----------------------------------------------------------------------------
81 
82 GlutPrimitiveNode::GlutPrimitiveNode(GlutPrimitiveType _type,
83  BaseNode* _parent,
84  const std::string & _name) :
85  BaseNode(_parent, _name),
86  setColor_(true)
87 {
88  const int slices = 20;
89  const int stacks = 20;
90 
91  // add a single primitive of the given type
92  Primitive p(_type);
93  primitives_.push_back(p);
94 
95  sphere_ = new ACG::GLSphere(slices, stacks);
96 }
97 
98 void
100 set_position(const Vec3d& _p, int _idx)
101 {
102  if (_idx > -1 && _idx < (int)primitives_.size())
103  primitives_[_idx].position = _p;
104 }
105 
106 //----------------------------------------------------------------------------
107 
108 const Vec3d
110 get_position(int _idx) const
111 {
112  if (_idx > -1 && _idx < (int)primitives_.size())
113  return primitives_[_idx].position;
114 
115  return Vec3d(-1,-1,-1);
116 }
117 
118 //----------------------------------------------------------------------------
119 
120 void
122 set_size(double _s, int _idx)
123 {
124  if (_idx > -1 && _idx < (int)primitives_.size())
125  primitives_[_idx].size = _s;
126 }
127 
128 //----------------------------------------------------------------------------
129 
130 double
132 get_size(int _idx) const
133 {
134  if (_idx > -1 && _idx < (int)primitives_.size())
135  return primitives_[_idx].size;
136  return -1;
137 }
138 
139 //----------------------------------------------------------------------------
140 
141 void
143 boundingBox(Vec3d& _bbMin, Vec3d& _bbMax)
144 {
145  for (int i = 0; i < (int)primitives_.size(); ++i)
146  {
147  Vec3d sizeVec(primitives_[i].size, primitives_[i].size, primitives_[i].size);
148  _bbMax.maximize(primitives_[i].position + sizeVec);
149  _bbMin.minimize(primitives_[i].position - sizeVec);
150  }
151 }
152 
153 //----------------------------------------------------------------------------
154 
158 {
159  return ( DrawModes::POINTS |
165 }
166 
167 //----------------------------------------------------------------------------
168 
169 void
171 draw(GLState& _state, const DrawModes::DrawMode& _drawMode)
172 {
173  Vec4f backupColorDiffuse;
174  Vec4f backupColorAmbient;
175  if ( setColor_ ) {
176  backupColorDiffuse = _state.diffuse_color();
177  backupColorAmbient = _state.ambient_color();
178  }
179  for (size_t i = 0; i < primitives_.size(); ++i)
180  {
181  _state.push_modelview_matrix();
182  _state.translate(primitives_[i].position[0], primitives_[i].position[1], primitives_[i].position[2]);
183 
184 
185  if (_drawMode & DrawModes::POINTS)
186  {
187  if(setColor_)
188  _state.set_color(primitives_[i].color);
189  ACG::GLState::disable(GL_LIGHTING);
190  ACG::GLState::shadeModel(GL_FLAT);
191  glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
192  draw_obj(_state, i);
193  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
194  }
195 
196 
197  if (_drawMode & DrawModes::WIREFRAME)
198  {
199  ACG::GLState::disable(GL_LIGHTING);
200  ACG::GLState::shadeModel(GL_FLAT);
201  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
202  _state.set_color(primitives_[i].color);
203  draw_obj(_state, i);
204  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
205  }
206 
207  if (_drawMode & DrawModes::SOLID_FACES_COLORED)
208  {
209  ACG::GLState::disable(GL_LIGHTING);
210  ACG::GLState::shadeModel(GL_FLAT);
211  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
212 
213  if ( setColor_ ) {
214  _state.set_diffuse_color(primitives_[i].color);
215  _state.set_ambient_color(primitives_[i].color);
216  _state.set_color(primitives_[i].color);
217  }
218 
219  draw_obj(_state, i);
220 
221  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
222  }
223 
224  if (_drawMode & DrawModes::HIDDENLINE)
225  {
226  Vec4f base_color_backup = _state.base_color();
227 
228  ACG::GLState::disable(GL_LIGHTING);
229  ACG::GLState::shadeModel(GL_FLAT);
230 
231  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
232  _state.set_color(_state.clear_color());
233  ACG::GLState::depthRange(0.01, 1.0);
234  draw_obj(_state, i);
235 
236  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
237  if(setColor_)
238  _state.set_color(primitives_[i].color);
239  else
240  _state.set_color(base_color_backup);
241  ACG::GLState::depthRange(0.0, 1.0);
242  draw_obj(_state, i);
243 
244  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
245  }
246 
247 
248  if (_drawMode & DrawModes::SOLID_FLAT_SHADED)
249  {
250  ACG::GLState::enable( GL_COLOR_MATERIAL );
251  ACG::GLState::enable(GL_LIGHTING);
252  ACG::GLState::shadeModel(GL_FLAT);
253 
254  if ( setColor_ ) {
255  _state.set_diffuse_color(primitives_[i].color);
256  _state.set_ambient_color(primitives_[i].color);
257  _state.set_color(primitives_[i].color);
258  }
259 
260  draw_obj(_state, i);
261  }
262 
263 
264  if (_drawMode & DrawModes::SOLID_SMOOTH_SHADED)
265  {
266  ACG::GLState::enable( GL_COLOR_MATERIAL );
267  ACG::GLState::enable(GL_LIGHTING);
268  ACG::GLState::shadeModel(GL_SMOOTH);
269 
270  if ( setColor_ ) {
271  _state.set_diffuse_color(primitives_[i].color);
272  _state.set_ambient_color(primitives_[i].color);
273  _state.set_color(primitives_[i].color);
274  //not sure if ambient and diffuse color have to be set here.
275  //the original call was:
276  //glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
277  //glColor(primitives_[i].color);
278  }
279 
280  draw_obj(_state, i);
281  }
282 
283  _state.pop_modelview_matrix();
284  if ( setColor_ ) {
285  _state.set_diffuse_color(backupColorDiffuse);
286  _state.set_ambient_color(backupColorAmbient);
287  }
288  } // end of primitives iter
289 }
290 
291 //----------------------------------------------------------------------------
292 
293 size_t
296 {
297  Primitive p(_type, _pos, _axis, _color);
298  primitives_.push_back(p);
299  return primitives_.size() - 1;
300 }
301 
302 //----------------------------------------------------------------------------
303 
304 void
305 GlutPrimitiveNode::draw_obj(GLState& _state, size_t _idx) const
306 {
307  if ( _idx >= primitives_.size()) // range check
308  return;
309 
310  Vec3d axis = primitives_[_idx].axis;
311  double size = axis.norm();
312 
313  if (size > 1e-10)
314  {
315  _state.push_modelview_matrix();
316  Vec3d direction = axis;
317  Vec3d z_axis(0,0,1);
318  Vec3d rot_normal;
319  double rot_angle;
320 
321  direction.normalize();
322  rot_angle = acos((z_axis | direction)) * 180 / M_PI;
323  rot_normal = ((z_axis % direction).normalize());
324 
325 
326  if (fabs(rot_angle) > 0.0001 && fabs(180 - rot_angle) > 0.0001)
327  {
328  _state.rotate(rot_angle,rot_normal[0], rot_normal[1], rot_normal[2]);
329  }
330  else
331  {
332  _state.rotate(rot_angle,1,0,0);
333  }
334 
335  switch (primitives_[_idx].type)
336  {
337  case CONE:
338  ACG::GLCone(primitives_[_idx].slices, primitives_[_idx].stacks, primitives_[_idx].size, 0.0f, true, true).draw(_state, primitives_[_idx].innersize);
339  break;
340 
341  case CUBE:
342  _state.scale(primitives_[_idx].size);
343  ACG::GLBox().draw_primitive();
344  break;
345 
346  case DODECAHEDRON:
347  ACG::GLDodecahedron().draw_primitive();
348  break;
349 
350  case ICOSAHEDRON:
351  ACG::GLIcosahedron().draw_primitive();
352  break;
353 
354  case OCTAHEDRON:
355  ACG::GLOctahedron().draw_primitive();
356  break;
357 
358  case SPHERE:
359  ACG::GLSphere(primitives_[_idx].slices, primitives_[_idx].stacks).draw(_state,primitives_[_idx].size);
360  break;
361 
362  case TETRAHEDRON:
363  ACG::GLTetrahedron().draw_primitive();
364  break;
365 
366  case TORUS:
367  ACG::GLTorus(primitives_[_idx].innersize, primitives_[_idx].size, primitives_[_idx].slices, primitives_[_idx].stacks).draw_primitive();
368  break;
369  }
370 
371  _state.pop_modelview_matrix();
372  }
373 }
374 
375 //----------------------------------------------------------------------------
376 
377 void
379 pick(GLState& _state , PickTarget _target)
380 {
381  // initialize picking stack
382  if (!_state.pick_set_maximum (primitives_.size()))
383  {
384  std::cerr << "Strange pickSetMaximum failed for index " << primitives_.size() << " in GlutPrimitiveNode\n";
385  return;
386  }
387 
388  switch (_target)
389  {
390  case PICK_ANYTHING:
391  case PICK_FACE:
392  {
393  for (size_t i = 0; i < primitives_.size(); ++i)
394  {
395  _state.pick_set_name(i);
396  _state.push_modelview_matrix();
397  _state.translate(primitives_[i].position[0], primitives_[i].position[1], primitives_[i].position[2]);
398  draw_obj(_state, i);
399  _state.pop_modelview_matrix();
400  }
401  break;
402  }
403 
404  default:
405  break;
406  }
407 }
408 
409 //----------------------------------------------------------------------------
410 
411 void
413 getRenderObjects(IRenderer* _renderer, GLState& _state , const DrawModes::DrawMode& _drawMode , const Material* _mat) {
414 
415  // init base render object
416  RenderObject ro;
417  ro.initFromState(&_state);
418 
419  // the selection sphere uses alpha blending against scene meshes
420  // set priority-order > 0 to draw this after meshes
421  ro.priority = 1;
422 
423  // enable depth-test
424  ro.depthTest = true;
425 
426  for (int i = 0; i < (int)primitives_.size(); ++i)
427  {
428 
429  // Set the right position
430  _state.push_modelview_matrix();
431  _state.translate(primitives_[i].position);
432  ro.modelview = _state.modelview();
433  _state.pop_modelview_matrix();
434 
435  Material localMaterial = *_mat;
436  if (setColor_)
437  {
438  //localMaterial.color(primitives_[i].color);
439  //localMaterial.ambientColor(primitives_[i].color);
440  localMaterial.diffuseColor(primitives_[i].color);
441  localMaterial.baseColor(primitives_[i].color * .5f);
442  }
443 
444  ro.setMaterial(&localMaterial);
445  ro.shaderDesc.shadeMode = SG_SHADE_PHONG;
446 
447  switch (primitives_[i].type) {
448  case SPHERE:
449 
450  // Sphere
451  ro.debugName = std::string("glutprimitive.sphere no ") + std::to_string(i) + ": " + name();
452 
453  sphere_->addToRenderer(_renderer, &ro, primitives_[i].size);
454 
455  break;
456 
457  default:
458  // TODO: The other glut primitives are not yet supported by the advanced renderers
459  std::cerr << "Sorry, but the glut renderer objects are not available for this renderer yet!" << std::endl;
460  break;
461  }
462 
463 
464  }
465 
466 }
467 
468 
469 //=============================================================================
470 } // namespace SceneGraph
471 } // namespace ACG
472 //=============================================================================
DrawMode SOLID_SMOOTH_SHADED
draw smooth shaded (Gouraud shaded) faces (requires halfedge normals)
Definition: DrawModes.cc:82
vector_type & maximize(const vector_type &_rhs)
maximize values: same as *this = max(*this, _rhs), but faster
Definition: Vector11T.hh:563
DrawMode WIREFRAME
draw wireframe
Definition: DrawModes.cc:78
Namespace providing different geometric functions concerning angles.
void set_ambient_color(const Vec4f &_col)
set ambient color
Definition: GLState.cc:707
pick any of the prior targets (should be implemented for all nodes)
Definition: PickTarget.hh:84
auto norm() const -> decltype(std::sqrt(std::declval< VectorT< S, DIM >>().sqrnorm()))
compute euclidean norm
Definition: Vector11T.hh:409
void set_diffuse_color(const Vec4f &_col)
set diffuse color
Definition: GLState.cc:722
void draw(GLState &_state, const DrawModes::DrawMode &_drawMode)
drawing the primitive
void push_modelview_matrix()
push modelview matrix
Definition: GLState.cc:1010
static void enable(GLenum _cap, bool _warnRemoved=true)
replaces glEnable, but supports locking
std::string name() const
Returns: name of node (needs not be unique)
double get_size(int _idx=0) const
get size
void getRenderObjects(IRenderer *_renderer, GLState &_state, const DrawModes::DrawMode &_drawMode, const Material *_mat)
Add the objects to the given renderer.
void set_color(const Vec4f &_col)
set color
Definition: GLState.cc:691
void translate(double _x, double _y, double _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
translate by (_x, _y, _z)
Definition: GLState.cc:533
void initFromState(GLState *_glState)
Initializes a RenderObject instance.
Definition: RenderObject.cc:61
void set_size(double _s, int _idx=0)
set size
GLMatrixd modelview
Modelview transform.
auto normalize() -> decltype(*this/=std::declval< VectorT< S, DIM >>().norm())
Definition: Vector11T.hh:429
static void disable(GLenum _cap, bool _warnRemoved=true)
replaces glDisable, but supports locking
const Vec4f & clear_color() const
get background color
Definition: GLState.hh:921
void pick(GLState &_state, PickTarget _target)
picking
void diffuseColor(const Vec4f &_d)
set the diffuse color.
Interface class between scenegraph and renderer.
Definition: RenderObject.hh:98
static void depthRange(GLclampd _zNear, GLclampd _zFar)
replaces glDepthRange, supports locking
DrawMode HIDDENLINE
draw hidden line (2 rendering passes needed)
Definition: DrawModes.cc:80
void boundingBox(Vec3d &_bbMin, Vec3d &_bbMax)
update bounding box
void baseColor(const Vec4f &_c)
set the base color (Sets the baseColor which is the same as the emission(const Vec4f& _c) ) ...
VectorT< double, 3 > Vec3d
Definition: VectorT.hh:121
DrawModes::DrawMode availableDrawModes() const
return available draw modes
static void shadeModel(GLenum _mode)
replaces glShadeModel, supports locking
size_t add_primitive(GlutPrimitiveType _type, Vec3d _pos, Vec3d _axis, ACG::Vec4f _color)
const Vec4f & base_color() const
get base color (used when lighting is off)
Definition: GLState.hh:926
const Vec3d get_position(int _idx=0) const
get position
const GLMatrixd & modelview() const
get modelview matrix
Definition: GLState.hh:791
ShaderGenDesc shaderDesc
Drawmode and other shader params.
PickTarget
What target to use for picking.
Definition: PickTarget.hh:73
DrawMode SOLID_FACES_COLORED
draw colored, but not lighted faces using face colors
Definition: DrawModes.cc:84
vector_type & minimize(const vector_type &_rhs)
minimize values: same as *this = min(*this, _rhs), but faster
Definition: Vector11T.hh:535
void rotate(double _angle, double _x, double _y, double _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
rotate around axis (_x, _y, _z) by _angle
Definition: GLState.cc:564
GlutPrimitiveType
Lists all available primivites.
void pop_modelview_matrix()
pop modelview matrix
Definition: GLState.cc:1026
void scale(double _s)
scale by (_s, _s, _s)
Definition: GLState.hh:750
DrawMode SOLID_FLAT_SHADED
draw flat shaded faces (requires face normals)
Definition: DrawModes.cc:81
picks faces (should be implemented for all nodes)
Definition: PickTarget.hh:78
void set_position(const Vec3d &_p, int _idx=0)
set position
const Vec4f & diffuse_color() const
get diffuse color
Definition: GLState.hh:936
const Vec4f & ambient_color() const
get ambient color
Definition: GLState.hh:931
DrawMode POINTS
draw unlighted points using the default base color
Definition: DrawModes.cc:73
bool pick_set_maximum(size_t _idx)
Set the maximal number of primitives/components of your object.
Definition: GLState.cc:1051
void pick_set_name(size_t _idx)
sets the current name/color (like glLoadName(_idx))
Definition: GLState.cc:1061
int priority
Priority to allow sorting of objects.