Developer Documentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
GLPrimitives.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  * $LastChangedBy$ *
46  * $Date$ *
47  * *
48  \*===========================================================================*/
49 
50 #include <ACG/GL/acg_glew.hh>
51 
52 #include "GLPrimitives.hh"
53 #include <ACG/GL/IRenderer.hh>
54 
55 
56 namespace ACG {
57 
58 //========================================================================
59 // GLPrimitive base class
60 //========================================================================
61 
62 GLPrimitive::GLPrimitive() :
63  vboDataInvalid_(true),
64  normalOrientation_(OUTSIDE),
65  numTris_(0),
66  numLines_(0),
67  vboData_(0),
68  curTriPtr_(0),
69  vbo_(0)
70 {
71 
72  vertexDecl_.addElement(GL_FLOAT, 3, VERTEX_USAGE_POSITION);
73  vertexDecl_.addElement(GL_FLOAT, 3, VERTEX_USAGE_NORMAL);
74  vertexDecl_.addElement(GL_FLOAT, 2, VERTEX_USAGE_TEXCOORD);
75 }
76 
77 //------------------------------------------------------------------------
78 
79 GLPrimitive::~GLPrimitive()
80 {
81  if (vbo_)
82  glDeleteBuffers(1, &vbo_);
83 
84  delete[] vboData_;
85 }
86 
87 //------------------------------------------------------------------------
88 
89 void GLPrimitive::addTriangleToVBO(const ACG::Vec3f* _p, const ACG::Vec3f* _n, const ACG::Vec2f* _tex)
90 {
91  if (!numTris_ || vboDataInvalid_)
92  numTris_ = getNumTriangles();
93 
94  if (!numTris_)
95  return;
96 
97  assert(numLines_ == 0);
98 
99 
100  if (!vboData_)
101  vboData_ = new float[8 * 3 * numTris_];
102 
103  if (curTriPtr_ == numTris_)
104  return;
105 
106  float* pTri = &vboData_[0] + (curTriPtr_++) * 3 * 8;
107 
108  // copy triangle
109  for (int i = 0; i < 3; ++i) {
110  for (int k = 0; k < 3; ++k)
111  *(pTri++) = _p[i][k];
112 
113  for (int k = 0; k < 3; ++k)
114  *(pTri++) = _n[i][k];
115 
116  for (int k = 0; k < 2; ++k)
117  *(pTri++) = _tex[i][k];
118  }
119 }
120 
121 
122 void GLPrimitive::addLineToVBO( const ACG::Vec3f* _p, const ACG::Vec3f* _n, const ACG::Vec2f* _tex )
123 {
124  if (!numLines_ || vboDataInvalid_)
125  numLines_ = getNumLines();
126 
127  if (!numLines_)
128  return;
129 
130  assert(numTris_ == 0);
131 
132  if (!vboData_)
133  vboData_ = new float[8 * 2 * numLines_];
134 
135  if (curTriPtr_ == numLines_)
136  return;
137 
138  float* pLine = &vboData_[0] + (curTriPtr_++) * 2 * 8;
139 
140  // copy line segment
141  for (int i = 0; i < 2; ++i) {
142  for (int k = 0; k < 3; ++k)
143  *(pLine++) = _p[i][k];
144 
145  for (int k = 0; k < 3; ++k)
146  *(pLine++) = _n[i][k];
147 
148  for (int k = 0; k < 2; ++k)
149  *(pLine++) = _tex[i][k];
150  }
151 }
152 
153 
154 //------------------------------------------------------------------------
155 
156 void GLPrimitive::bindVBO()
157 {
158  if (checkVBO())
159  {
160  glBindBuffer(GL_ARRAY_BUFFER, vbo_);
161 
162  glVertexPointer(3, GL_FLOAT, 32, 0);
163  glEnableClientState(GL_VERTEX_ARRAY);
164 
165  glNormalPointer(GL_FLOAT, 32, (GLvoid*) 12);
166  glEnableClientState(GL_NORMAL_ARRAY);
167 
168  glClientActiveTexture(GL_TEXTURE0);
169  glTexCoordPointer(2, GL_FLOAT, 32, (GLvoid*) 24);
170  glEnableClientState(GL_TEXTURE_COORD_ARRAY);
171  }
172 }
173 
174 //------------------------------------------------------------------------
175 
176 
177 bool GLPrimitive::checkVBO()
178 {
179  // create vbo if not done yet
180  // update vbo data and upload to gpu if needed
181  // return false iff vbo empty
182 
183  const int bufSize = numTris_ ? numTris_ * 3 * 8 * 4 : numLines_ * 2 * 8 * 4;
184 
185  if (!vbo_) {
186  if (!vboData_ || (!numTris_ && !numLines_) || (numTris_ && numLines_))
187  return false;
188 
189  // create vbo
190  glGenBuffers(1, &vbo_);
191  glBindBuffer(GL_ARRAY_BUFFER, vbo_);
192  glBufferData(GL_ARRAY_BUFFER, bufSize, vboData_, GL_STATIC_DRAW);
193 
194  delete[] vboData_;
195  vboData_ = 0;
196  } else if (vboDataInvalid_) {
197  updateVBOData();
198  glBindBuffer(GL_ARRAY_BUFFER, vbo_);
199  glBufferData(GL_ARRAY_BUFFER, bufSize, vboData_, GL_STATIC_DRAW);
200  vboDataInvalid_ = false;
201  }
202 
203  return true;
204 }
205 
206 //------------------------------------------------------------------------
207 
208 void GLPrimitive::unBindVBO()
209 {
210  glBindBuffer(GL_ARRAY_BUFFER, 0);
211  glDisableClientState(GL_VERTEX_ARRAY);
212  glDisableClientState(GL_NORMAL_ARRAY);
213  glDisableClientState(GL_TEXTURE_COORD_ARRAY);
214 }
215 
216 //------------------------------------------------------------------------
217 
218 void GLPrimitive::draw_primitive()
219 {
220  bindVBO();
221 
222  if (numTris_)
223  glDrawArrays(GL_TRIANGLES, 0, numTris_ * 3);
224  else
225  glDrawArrays(GL_LINES, 0, numLines_ * 2);
226 
227  unBindVBO();
228 }
229 
230 //------------------------------------------------------------------------
231 
232 void GLPrimitive::draw_primitive(GLSL::Program* _program)
233 {
234  if (checkVBO())
235  {
236  glBindBuffer(GL_ARRAY_BUFFER, vbo_);
237  vertexDecl_.activateShaderPipeline(_program);
238 
239  if (numTris_)
240  glDrawArrays(GL_TRIANGLES, 0, numTris_ * 3);
241  else
242  glDrawArrays(GL_LINES, 0, numLines_ * 2);
243 
244  vertexDecl_.deactivateShaderPipeline(_program);
245  glBindBuffer(GL_ARRAY_BUFFER, 0);
246  }
247 }
248 
249 //------------------------------------------------------------------------
250 
251 void GLPrimitive::addToRenderer_primitive( class IRenderer* _renderer, RenderObject* _ro )
252 {
253  if (checkVBO())
254  {
255  _ro->vertexBuffer = vbo_;
256  _ro->vertexDecl = &vertexDecl_;
257 
258  if (numTris_)
259  _ro->glDrawArrays(GL_TRIANGLES, 0, numTris_ * 3);
260  else
261  _ro->glDrawArrays(GL_LINES, 0, numLines_ * 2);
262 
263  _renderer->addRenderObject(_ro);
264  }
265 }
266 
267 //------------------------------------------------------------------------
268 
269 void GLPrimitive::updateVBOData() {
270  curTriPtr_ = 0;
271 
272  if (vboData_) {
273  delete[] vboData_;
274  vboData_ = 0;
275  }
276 
277  updateVBO();
278 }
279 
280 //------------------------------------------------------------------------
281 
282 unsigned int GLPrimitive::getVBO()
283 {
284  return checkVBO() ? vbo_ : 0;
285 }
286 
287 const VertexDeclaration* GLPrimitive::getVertexDecl() const
288 {
289  return &vertexDecl_;
290 }
291 
292 //========================================================================
293 // GLSphere
294 //========================================================================
295 
296 
297 
298 GLSphere::GLSphere(int _slices, int _stacks) :
299  slices_(_slices),
300  stacks_(_stacks)
301 {
302  updateVBO();
303 }
304 
305 //------------------------------------------------------------------------
306 
307 GLSphere::~GLSphere()
308 {
309 
310 }
311 
312 //------------------------------------------------------------------------
313 
314 void GLSphere::draw(GLState& _state, float _radius, const ACG::Vec3f& _center)
315 {
316  _state.push_modelview_matrix();
317 
318  _state.translate(ACG::Vec3d(_center));
319  _state.scale(_radius, _radius, _radius);
320 
321  GLPrimitive::draw_primitive();
322 
323  _state.pop_modelview_matrix();
324 }
325 
326 //------------------------------------------------------------------------
327 
328 void GLSphere::addToRenderer( IRenderer* _renderer, const RenderObject* _base, float _radius, const ACG::Vec3f& _center /*= ACG::Vec3f(0.0f, 0.0f, 0.0f)*/ )
329 {
330  RenderObject ro = *_base;
331 
332  ro.modelview.translate(ACG::Vec3d(_center));
333  ro.modelview.scale((double)_radius, (double)_radius, (double)_radius);
334 
335  GLPrimitive::addToRenderer_primitive(_renderer, &ro);
336 }
337 
338 
339 //------------------------------------------------------------------------
340 
341 int GLSphere::getNumTriangles()
342 {
343  return 2 * slices_ + (stacks_ - 2) * slices_ * 2;
344 }
345 
346 //------------------------------------------------------------------------
347 
348 void GLSphere::updateVBO()
349 {
350  for (int sl = 0; sl < slices_; ++sl) {
351  // top triangle:
352  {
353  int st = 0;
354  addTriangle(0, st, sl + 1, st + 1, sl, st + 1);
355  }
356  // middle quads:
357  for (int st = 1; st < stacks_ - 1; ++st) {
358  addTriangle(sl, st, sl + 1, st, sl, st + 1);
359  addTriangle(sl + 1, st, sl + 1, st + 1, sl, st + 1);
360  }
361  // bottom triangle:
362  {
363  addTriangle(0, stacks_, sl, stacks_ - 1, sl + 1, stacks_ - 1);
364  }
365  }
366 }
367 
368 //------------------------------------------------------------------------
369 
370 void GLSphere::addTriangle(int sl0, int st0, int sl1, int st1, int sl2, int st2)
371 {
372  ACG::Vec3f p[3];
373  ACG::Vec3f n[3];
374  ACG::Vec2f tex[3];
375 
376  n[0] = p[0] = positionOnSphere(sl0, st0);
377  n[1] = p[1] = positionOnSphere(sl1, st1);
378  n[2] = p[2] = positionOnSphere(sl2, st2);
379  n[0].normalize();
380  n[1].normalize();
381  n[2].normalize();
382  tex[0] = texCoordOnSphere(sl0, st0);
383  tex[1] = texCoordOnSphere(sl1, st1);
384  tex[2] = texCoordOnSphere(sl2, st2);
385 
386  addTriangleToVBO(p, n, tex);
387 }
388 
389 //------------------------------------------------------------------------
390 
391 ACG::Vec3f GLSphere::positionOnSphere(int _sliceNumber, int _stackNumber)
392 {
393  ACG::Vec3f position;
394 
395  double alpha = (M_PI / double(stacks_)) * double(_stackNumber);
396  double beta = ((2.0 * M_PI) / double(slices_)) * double(_sliceNumber);
397 
398  double ringRadius = sin(alpha);
399  position[0] = sin(beta) * ringRadius;
400  position[1] = cos(beta) * ringRadius;
401  position[2] = cos(alpha);
402 
403  return position;
404 }
405 
406 //------------------------------------------------------------------------
407 
408 ACG::Vec2f GLSphere::texCoordOnSphere(int _sliceNumber, int _stackNumber)
409 {
410  ACG::Vec2f texCoord;
411 
412  double alpha = (M_PI / double(stacks_)) * double(_stackNumber);
413  texCoord[0] = double(_sliceNumber) / double(slices_);
414  texCoord[1] = 0.5 * (cos(alpha) + 1.0);
415 
416  return texCoord;
417 }
418 
419 //========================================================================
420 // GLCone
421 //========================================================================
422 
423 GLCone::GLCone(int _slices, int _stacks, float _bottomRadius, float _topRadius, bool _bottomCap, bool _topCap) :
424  slices_(_slices),
425  stacks_(_stacks),
426  bottomRadius_(_bottomRadius),
427  topRadius_(_topRadius),
428  bottomCap_(_bottomCap),
429  topCap_(_topCap)
430 {
431  updateVBO();
432 }
433 
434 //------------------------------------------------------------------------
435 
436 GLCone::~GLCone()
437 {
438 
439 }
440 
441 //------------------------------------------------------------------------
442 
443 void GLCone::setBottomRadius(float _bottomRadius) {
444  if (bottomRadius_ != _bottomRadius)
445  vboDataInvalid_ = true;
446  bottomRadius_ = _bottomRadius;
447 }
448 
449 //------------------------------------------------------------------------
450 
451 void GLCone::setTopRadius(float _topRadius) {
452  if (topRadius_ != _topRadius)
453  vboDataInvalid_ = true;
454  topRadius_ = _topRadius;
455 }
456 
457 //------------------------------------------------------------------------
458 
459 void GLCone::setNormalOrientation(NormalOrientation orientation) {
460  if (normalOrientation_ != orientation)
461  vboDataInvalid_ = true;
462  normalOrientation_ = orientation;
463 }
464 
465 //------------------------------------------------------------------------
466 
467 void GLCone::draw(GLState& _state, float _height, const ACG::Vec3f& _center, ACG::Vec3f _upDir)
468 {
469 // ACG::mat4 mWorld = ACG::translate(ACG::mat4(1.0f), _center);
470 
471  _state.push_modelview_matrix();
472 
473  // translate
474  _state.translate(ACG::Vec3d(_center));
475 
476  _upDir.normalize();
477 
478  // compute rotation matrix mAlign
479  // such that vBindDir rotates to _upDir
480  ACG::GLMatrixd mAlign;
481  mAlign.identity();
482 
483  ACG::Vec3f vBindDir(0.0f, 0.0f, 1.0f);
484 
485  ACG::Vec3f vRotAxis = OpenMesh::cross(_upDir, vBindDir);
486  vRotAxis.normalize();
487 
488  ACG::Vec3f vUp = OpenMesh::cross(_upDir, vRotAxis);
489 
490  // rotate
491  for (int i = 0; i < 3; ++i) {
492  mAlign(i, 0) = vRotAxis[i];
493  mAlign(i, 1) = vUp[i];
494  mAlign(i, 2) = _upDir[i];
495  }
496 
497  ACG::Vec3f vDelta = vBindDir - _upDir;
498  if ( fabsf(OpenMesh::dot(vDelta, vDelta)) < 1e-3f)
499  mAlign.identity();
500 
501  // scale
502  mAlign.scale(1.0, 1.0, _height);
503 
504  ACG::GLMatrixd mAlignInv(mAlign);
505  mAlignInv.invert();
506 
507  _state.mult_matrix(mAlign, mAlignInv);
508 
509  GLPrimitive::draw_primitive();
510 
511  _state.pop_modelview_matrix();
512 }
513 
514 //------------------------------------------------------------------------
515 
516 
517 void GLCone::addToRenderer(IRenderer* _renderer,
518  const RenderObject* _base,
519  float _height,
520  const ACG::Vec3f& _center,
521  ACG::Vec3f _upDir,
522  float _radiusScale)
523 {
524  RenderObject ro = *_base;
525 
526  // translate
527  ro.modelview.translate(ACG::Vec3d(_center));
528 
529  _upDir.normalize();
530 
531  // compute rotation matrix mAlign
532  // such that vBindDir rotates to _upDir
533  ACG::GLMatrixf mAlign;
534  mAlign.identity();
535 
536  ACG::Vec3f vBindDir(0.0f, 0.0f, 1.0f);
537 
538  ACG::Vec3f vRotAxis = OpenMesh::cross(_upDir, vBindDir);
539  vRotAxis.normalize();
540 
541  ACG::Vec3f vUp = OpenMesh::cross(_upDir, vRotAxis);
542 
543  // rotate
544  for (int i = 0; i < 3; ++i) {
545  mAlign(i, 0) = vRotAxis[i];
546  mAlign(i, 1) = vUp[i];
547  mAlign(i, 2) = _upDir[i];
548  }
549 
550  ACG::Vec3f vDelta = vBindDir - _upDir;
551  if ( fabsf(OpenMesh::dot(vDelta, vDelta)) < 1e-3f)
552  mAlign.identity();
553 
554  // scale
555  mAlign.scale(_radiusScale, _radiusScale, _height);
556 
557  ro.modelview *= mAlign;
558 
559  GLPrimitive::addToRenderer_primitive(_renderer, &ro);
560 }
561 
562 //------------------------------------------------------------------------
563 
564 int GLCone::getNumTriangles()
565 {
566  int numTris = stacks_ * slices_ * 2;
567 
568  if (bottomCap_)
569  numTris += slices_;
570  if (topCap_)
571  numTris += slices_;
572 
573  return numTris;
574 }
575 
576 //------------------------------------------------------------------------
577 
578 ACG::Vec3f GLCone::positionOnCone(int _sliceNumber, int _stackNumber)
579 {
580  ACG::Vec3f position;
581 
582  double beta = ((2.0 * M_PI) / slices_) * _sliceNumber;
583 
584  double relativeHeight = _stackNumber / (double) stacks_;
585  double ringRadius = (1.0 - relativeHeight) * bottomRadius_ + relativeHeight * topRadius_;
586  position[0] = sin(beta) * ringRadius;
587  position[1] = cos(beta) * ringRadius;
588  position[2] = relativeHeight;
589 
590  return position;
591 }
592 
593 //------------------------------------------------------------------------
594 
595 ACG::Vec2f GLCone::texCoordOnCone(int _sliceNumber, int _stackNumber)
596 {
597  ACG::Vec2f texCoord;
598 
599  texCoord[0] = _sliceNumber / (double) slices_;
600  texCoord[1] = _stackNumber / (double) stacks_;
601 
602  return texCoord;
603 }
604 
605 //------------------------------------------------------------------------
606 
607 ACG::Vec3f GLCone::normalOnCone(int _sliceNumber, int _stackNumber)
608 {
609  ACG::Vec3f normal;
610 
611  double beta = ((2.0 * M_PI) / slices_) * _sliceNumber;
612  double relativeHeight = _stackNumber / (double) stacks_;
613  double ringRadius = (1.0 - relativeHeight) * bottomRadius_ + relativeHeight * topRadius_;
614 
615  normal[0] = sin(beta) * ringRadius;
616  normal[1] = cos(beta) * ringRadius;
617  normal[2] = (bottomRadius_ - topRadius_);
618 
619  normal.normalize();
620  return normal;
621 }
622 
623 //------------------------------------------------------------------------
624 
625 void GLCone::addTriangle(int sl0, int st0, int sl1, int st1, int sl2, int st2)
626 {
627  ACG::Vec3f p[3];
628  ACG::Vec3f n[3];
629  ACG::Vec2f tex[3];
630 
631  p[0] = positionOnCone(sl0, st0);
632  p[1] = positionOnCone(sl1, st1);
633  p[2] = positionOnCone(sl2, st2);
634  if (normalOrientation_ == OUTSIDE) {
635  n[0] = normalOnCone(sl0, st0);
636  n[1] = normalOnCone(sl1, st1);
637  n[2] = normalOnCone(sl2, st2);
638  } else if (normalOrientation_ == INSIDE) {
639  n[0] = -normalOnCone(sl0, st0);
640  n[1] = -normalOnCone(sl1, st1);
641  n[2] = -normalOnCone(sl2, st2);
642  }
643  tex[0] = texCoordOnCone(sl0, st0);
644  tex[1] = texCoordOnCone(sl1, st1);
645  tex[2] = texCoordOnCone(sl2, st2);
646 
647  addTriangleToVBO(p, n, tex);
648 }
649 
650 //------------------------------------------------------------------------
651 
652 void GLCone::updateVBO()
653 {
654  for (int sl = 0; sl < slices_; ++sl) {
655  // top triangle:
656  if (topCap_) {
657  ACG::Vec3f p[3];
658  ACG::Vec3f n[3];
659  ACG::Vec2f tex[3];
660 
661  p[0] = ACG::Vec3f(0.0, 0.0, 1.0);
662  p[1] = positionOnCone(sl + 1, stacks_);
663  p[2] = positionOnCone(sl, stacks_);
664  if (normalOrientation_ == OUTSIDE) {
665  n[0] = ACG::Vec3f(0.0, 0.0, 1.0);
666  n[1] = ACG::Vec3f(0.0, 0.0, 1.0);
667  n[2] = ACG::Vec3f(0.0, 0.0, 1.0);
668  } else if (normalOrientation_ == INSIDE) {
669  n[0] = ACG::Vec3f(0.0, 0.0, -1.0);
670  n[1] = ACG::Vec3f(0.0, 0.0, -1.0);
671  n[2] = ACG::Vec3f(0.0, 0.0, -1.0);
672  }
673 
674  tex[0] = ACG::Vec2f(0.5, 0.5);
675  double beta = ((2.0 * M_PI) / slices_) * (sl + 1);
676  tex[1] = ACG::Vec2f(sin(beta), cos(beta));
677  beta = ((2.0 * M_PI) / slices_) * (sl);
678  tex[2] = ACG::Vec2f(sin(beta), cos(beta));
679 
680  addTriangleToVBO(p, n, tex);
681  }
682  // middle quads:
683  for (int st = 0; st < stacks_; ++st) {
684  addTriangle(sl, st, sl, st + 1, sl + 1, st);
685  addTriangle(sl + 1, st, sl, st + 1, sl + 1, st + 1);
686  }
687  // bottom triangle:
688  if (bottomCap_) {
689  ACG::Vec3f p[3];
690  ACG::Vec3f n[3];
691  ACG::Vec2f tex[3];
692 
693  p[0] = ACG::Vec3f(0.0, 0.0, 0.0);
694  p[1] = positionOnCone(sl, 0);
695  p[2] = positionOnCone(sl + 1, 0);
696  if (normalOrientation_ == OUTSIDE) {
697  n[0] = ACG::Vec3f(0.0, 0.0, -1.0);
698  n[1] = ACG::Vec3f(0.0, 0.0, -1.0);
699  n[2] = ACG::Vec3f(0.0, 0.0, -1.0);
700  } else if (normalOrientation_ == INSIDE) {
701  n[0] = ACG::Vec3f(0.0, 0.0, 1.0);
702  n[1] = ACG::Vec3f(0.0, 0.0, 1.0);
703  n[2] = ACG::Vec3f(0.0, 0.0, 1.0);
704  }
705 
706  tex[0] = ACG::Vec2f(0.5, 0.5);
707  double beta = ((2.0 * M_PI) / slices_) * (sl);
708  tex[1] = ACG::Vec2f(sin(beta), cos(beta));
709  beta = ((2.0 * M_PI) / slices_) * (sl + 1);
710  tex[2] = ACG::Vec2f(sin(beta), cos(beta));
711 
712  addTriangleToVBO(p, n, tex);
713  }
714  }
715 }
716 
717 //========================================================================
718 // GLCylinder
719 //========================================================================
720 
721 GLCylinder::GLCylinder(int _slices, int _stacks, float _radius, bool _bottomCap, bool _topCap) :
722  GLCone(_slices, _stacks, _radius, _radius, _bottomCap, _topCap)
723 {
724 }
725 
726 //========================================================================
727 // GLPartialDisk
728 //========================================================================
729 
738 GLPartialDisk::GLPartialDisk(int _slices, int _loops, float _innerRadius, float _outerRadius, float _startAngle, float _sweepAngle) :
739  slices_(_slices),
740  loops_(_loops),
741  innerRadius_(_innerRadius),
742  outerRadius_(_outerRadius),
743  startAngle_(_startAngle),
744  sweepAngle_(_sweepAngle)
745 {
746  updateVBO();
747 }
748 
749 //------------------------------------------------------------------------
750 
751 void GLPartialDisk::setInnerRadius(float _innerRadius) {
752  if (innerRadius_ != _innerRadius)
753  vboDataInvalid_ = true;
754  innerRadius_ = _innerRadius;
755 }
756 
757 //------------------------------------------------------------------------
758 
759 void GLPartialDisk::setOuterRadius(float _outerRadius) {
760  if (outerRadius_ != _outerRadius)
761  vboDataInvalid_ = true;
762  outerRadius_ = _outerRadius;
763 }
764 
765 //------------------------------------------------------------------------
766 
767 int GLPartialDisk::getNumTriangles() {
768  return slices_ * (loops_+1) * 2;
769 }
770 
771 //------------------------------------------------------------------------
772 
773 void GLPartialDisk::updateVBO() {
774  assert(slices_ >= 2);
775  assert(loops_ >= 1);
776  assert(outerRadius_ > 0.0f);
777  assert(innerRadius_ >= 0.0f);
778  assert(innerRadius_ < outerRadius_);
779 
780  if (sweepAngle_ < -360.0f)
781  sweepAngle_ = 360.0f;
782  if (sweepAngle_ > 360.0f)
783  sweepAngle_ = 360.0f;
784  if (sweepAngle_ < 0) {
785  startAngle_ += sweepAngle_;
786  sweepAngle_ = -sweepAngle_;
787  }
788 
789  float* sinCache = new float[slices_+1];
790  float* cosCache = new float[slices_+1];
791 
792  // precompute all sine and cosine that are needed
793  float angleOffsetRadian = startAngle_ * M_PI / 180.0f;
794  float sweepAngleRadian = sweepAngle_ * M_PI / 180.0f;
795  for (int i = 0; i < slices_+1; ++i) {
796  float angle = angleOffsetRadian + sweepAngleRadian * i/slices_;
797  sinCache[i] = sin(angle);
798  cosCache[i] = cos(angle);
799  }
800 
801  // iterate over loops (starting from the inner most) to generate triangles
802  float deltaRadius = outerRadius_ - innerRadius_;
803  for (int i = loops_+1; i > 0; --i) {
804 
805  // for each slice generate two triangles
806  for (int j = 0; j < slices_; ++j) {
807 
808  ACG::Vec3f p[3];
809  ACG::Vec3f n[3];
810  ACG::Vec2f tex[3];
811  ACG::Vec3f p2[3];
812  ACG::Vec3f n2[3];
813  ACG::Vec2f tex2[3];
814 
815  // radius of the loop nearer to the center of the disk
816  float innerRadius = outerRadius_ - deltaRadius * ((float) i / (loops_ + 1));
817  // radius of the loop further from the center of the disk
818  float outerRadius = outerRadius_ - deltaRadius * ((float) (i - 1) / (loops_ + 1));
819 
820  // first triangle:
821  // 1 2
822  //
823  // 0
824  // vertices
825  p[0] = ACG::Vec3f(innerRadius * sinCache[j], innerRadius * cosCache[j], 0.0f);
826  p[1] = ACG::Vec3f(outerRadius * sinCache[j], outerRadius * cosCache[j], 0.0f);
827  p[2] = ACG::Vec3f(outerRadius * sinCache[j+1], outerRadius * cosCache[j+1], 0.0f);
828  // normals
829  n[0] = ACG::Vec3f(0.0f, 0.0f, 1.0f);
830  n[1] = ACG::Vec3f(0.0f, 0.0f, 1.0f);
831  n[2] = ACG::Vec3f(0.0f, 0.0f, 1.0f);
832  // TODO: proper texture coordinates
833  tex[0] = ACG::Vec2f(0.0f, 0.0f);
834  tex[1] = ACG::Vec2f(0.0f, 0.0f);
835  tex[2] = ACG::Vec2f(0.0f, 0.0f);
836 
837  addTriangleToVBO(p, n, tex);
838 
839  // second triangle:
840  // x 1
841  //
842  // 0 2
843  // vertices
844  p2[0] = ACG::Vec3f(innerRadius * sinCache[j], innerRadius * cosCache[j], 0.0f);
845  p2[1] = ACG::Vec3f(outerRadius * sinCache[j+1], outerRadius * cosCache[j+1], 0.0f);
846  p2[2] = ACG::Vec3f(innerRadius * sinCache[j+1], innerRadius * cosCache[j+1], 0.0f);
847  // normals
848  n2[0] = ACG::Vec3f(0.0f, 0.0f, 1.0f);
849  n2[1] = ACG::Vec3f(0.0f, 0.0f, 1.0f);
850  n2[2] = ACG::Vec3f(0.0f, 0.0f, 1.0f);
851  // TODO: proper texture coordinates
852  tex2[0] = ACG::Vec2f(0.0f, 0.0f);
853  tex2[1] = ACG::Vec2f(0.0f, 0.0f);
854  tex2[2] = ACG::Vec2f(0.0f, 0.0f);
855 
856  addTriangleToVBO(p2, n2, tex2);
857 
858  }
859  }
860 
861  delete[] sinCache;
862  delete[] cosCache;
863 }
864 
865 //------------------------------------------------------------------------
866 
867 void GLPartialDisk::draw( GLState& _state, const ACG::Vec3f& _center, ACG::Vec3f _upDir) {
868  _state.push_modelview_matrix();
869 
870  // translate
871  _state.translate(ACG::Vec3d(_center));
872 
873  _upDir.normalize();
874 
875  // compute rotation matrix mAlign
876  // such that vBindDir rotates to _upDir
877  ACG::GLMatrixd mAlign;
878  mAlign.identity();
879 
880  ACG::Vec3f vBindDir(0.0f, 0.0f, 1.0f);
881 
882  ACG::Vec3f vRotAxis = OpenMesh::cross(_upDir, vBindDir);
883  vRotAxis.normalize();
884 
885  ACG::Vec3f vUp = OpenMesh::cross(_upDir, vRotAxis);
886 
887  // rotate
888  for (int i = 0; i < 3; ++i) {
889  mAlign(i, 0) = vRotAxis[i];
890  mAlign(i, 1) = vUp[i];
891  mAlign(i, 2) = _upDir[i];
892  }
893 
894  ACG::Vec3f vDelta = vBindDir - _upDir;
895  if ( fabsf(OpenMesh::dot(vDelta, vDelta)) < 1e-3f)
896  mAlign.identity();
897 
898  ACG::GLMatrixd mAlignInv(mAlign);
899  mAlignInv.invert();
900 
901  _state.mult_matrix(mAlign, mAlignInv);
902 
903  GLPrimitive::draw_primitive();
904 
905  _state.pop_modelview_matrix();
906 }
907 
908 //========================================================================
909 // GLDisk
910 //========================================================================
911 
918 GLDisk::GLDisk(int _slices, int _loops, float _innerRadius, float _outerRadius) :
919  GLPartialDisk(_slices, _loops, _innerRadius, _outerRadius, 0.0f, 360.0f)
920 {
921 }
922 
923 
924 //========================================================================
925 // GLBox
926 //========================================================================
927 
928 GLBox::GLBox()
929 {
930  updateVBO();
931 }
932 
933 GLBox::~GLBox()
934 {
935 }
936 
937 int GLBox::getNumTriangles()
938 {
939  return 12;
940 }
941 
942 //------------------------------------------------------------------------
943 
944 void GLBox::updateVBO()
945 {
946  static const Vec3f pos[8] =
947  {
948  Vec3f(-0.5f,-0.5f,0.5f), Vec3f(-0.5f,-0.5f,-0.5f), Vec3f(0.5f,-0.5f,-0.5f),
949  Vec3f(0.5f,-0.5f,0.5f), Vec3f(-0.5f,0.5f,0.5f), Vec3f(0.5f,0.5f,0.5f),
950  Vec3f(0.5f,0.5f,-0.5f), Vec3f(-0.5f,0.5f,-0.5f)
951  };
952 
953  static const Vec3f norm[6] =
954  {
955  Vec3f(0.0f,-1.0f,0.0f), Vec3f(0.0f,1.0f,0.0f), Vec3f(0.0f,0.0f,1.0f),
956  Vec3f(1.0f,0.0f,0.0f), Vec3f(0.0f,0.0f,-1.0f), Vec3f(-1.0f,0.0f,0.0f)
957  };
958 
959  static const Vec2f texc[4] =
960  {
961  Vec2f(1.0f,0.0f), Vec2f(1.0f,1.0f), Vec2f(0.0f,1.0f), Vec2f(0.0f,0.0f)
962  };
963 
964  // tri: p,p,p ,n,n,n ,t,t,t
965  static const int tris[12][9] =
966  {
967  {0,1,2 ,0,0,0 ,0,1,2}, {2,3,0 ,0,0,0 ,2,3,0}, {4,5,6 ,1,1,1 ,3,0,1},
968  {6,7,4 ,1,1,1 ,1,2,3}, {0,3,5 ,2,2,2 ,3,0,1}, {5,4,0 ,2,2,2 ,1,2,3},
969  {3,2,6 ,3,3,3 ,3,0,1}, {6,5,3 ,3,3,3 ,1,2,3}, {2,1,7 ,4,4,4 ,3,0,1},
970  {7,6,2 ,4,4,4 ,1,2,3}, {1,0,4 ,5,5,5 ,3,0,1}, {4,7,1 ,5,5,5 ,1,2,3}
971  };
972 
973  for (int i = 0; i < 12; ++i)
974  {
975  Vec3f triPos[3] = { pos[tris[i][0]], pos[tris[i][1]], pos[tris[i][2]] };
976  Vec3f triNorm[3] = { norm[tris[i][3]], norm[tris[i][4]], norm[tris[i][5]] };
977  Vec2f triTexc[3] = { texc[tris[i][6]], texc[tris[i][7]], texc[tris[i][8]] };
978 
979  addTriangleToVBO(triPos, triNorm, triTexc);
980  }
981 }
982 
983 //------------------------------------------------------------------------
984 
985 GLLineBox::GLLineBox()
986 {
987  updateVBO();
988 }
989 
990 GLLineBox::~GLLineBox()
991 {
992 }
993 
994 //------------------------------------------------------------------------
995 
996 int GLLineBox::getNumTriangles()
997 {
998  return 0;
999 }
1000 
1001 int GLLineBox::getNumLines()
1002 {
1003  return 12;
1004 }
1005 
1006 //------------------------------------------------------------------------
1007 
1008 void GLLineBox::updateVBO()
1009 {
1010  static const Vec3f pos[8] =
1011  {
1012  Vec3f(-0.5f,-0.5f,0.5f), Vec3f(-0.5f,-0.5f,-0.5f), Vec3f(0.5f,-0.5f,-0.5f),
1013  Vec3f(0.5f,-0.5f,0.5f), Vec3f(-0.5f,0.5f,0.5f), Vec3f(0.5f,0.5f,0.5f),
1014  Vec3f(0.5f,0.5f,-0.5f), Vec3f(-0.5f,0.5f,-0.5f)
1015  };
1016 
1017  static const Vec3f norm[6] =
1018  {
1019  Vec3f(0.0f,-1.0f,0.0f), Vec3f(0.0f,1.0f,0.0f), Vec3f(0.0f,0.0f,1.0f),
1020  Vec3f(1.0f,0.0f,0.0f), Vec3f(0.0f,0.0f,-1.0f), Vec3f(-1.0f,0.0f,0.0f)
1021  };
1022 
1023  static const Vec2f texc[4] =
1024  {
1025  Vec2f(1.0f,0.0f), Vec2f(1.0f,1.0f), Vec2f(0.0f,1.0f), Vec2f(0.0f,0.0f)
1026  };
1027 
1028  // line: p,p ,n,n ,t,t
1029  static const int lines[12][6] =
1030  {
1031  {1,2, 0,0, 0,3}, {0,3, 0,0, 0,3}, {4,5, 0,0, 0,3}, {7,6, 0,0, 0,3},
1032  {1,7, 0,0, 0,3}, {0,4, 0,0, 0,3}, {2,6, 0,0, 0,3}, {3,5, 0,0, 0,3},
1033  {1,0, 0,0, 0,3}, {2,3, 0,0, 0,3}, {7,4, 0,0, 0,3}, {6,5, 0,0, 0,3}
1034  };
1035 
1036  for (int i = 0; i < 12; ++i)
1037  {
1038  Vec3f p[2] = { pos[lines[i][0]], pos[lines[i][1]]};
1039  Vec3f n[2] = { norm[lines[i][2]], norm[lines[i][3]]};
1040  Vec2f t[2] = { texc[lines[i][4]], texc[lines[i][5]]};
1041 
1042  addLineToVBO(p, n, t);
1043  }
1044 }
1045 
1046 //------------------------------------------------------------------------
1047 
1048 }
T angle(T _cos_angle, T _sin_angle)
Definition: MathDefs.hh:145
GLPartialDisk(int _slices, int _loops, float _innerRadius, float _outerRadius, float _startAngle, float _sweepAngle)
osg::Vec3f::ValueType dot(const osg::Vec3f &_v1, const osg::Vec3f &_v2)
Adapter for osg vector member computing a scalar product.
Namespace providing different geometric functions concerning angles.
Definition: DBSCANT.cc:51
GLDisk(int _slices, int _loops, float _innerRadius, float _outerRadius)
VectorT< float, 3 > Vec3f
Definition: VectorT.hh:125
VectorT< float, 2 > Vec2f
Definition: VectorT.hh:108
void activateShaderPipeline(GLSL::Program *_prog) const
GLSL program class.
Definition: GLSLShader.hh:217
void deactivateShaderPipeline(GLSL::Program *_prog) const
void scale(Scalar _x, Scalar _y, Scalar _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
multiply self with scaling matrix (x,y,z)
Definition: GLMatrixT.cc:81
osg::Vec3f cross(const osg::Vec3f &_v1, const osg::Vec3f &_v2)
Adapter for osg vector member computing a scalar product.
void identity()
setup an identity matrix
Definition: Matrix4x4T.cc:256