Developer Documentation
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 #include <ACG/GL/acg_glew.hh>
44 
45 #include "GLPrimitives.hh"
46 #include <ACG/GL/IRenderer.hh>
47 
48 namespace ACG {
49 
50 //========================================================================
51 // GLPrimitive base class
52 //========================================================================
53 
54 GLPrimitive::GLPrimitive() :
55  vboDataInvalid_(true),
56  normalOrientation_(OUTSIDE),
57  numTris_(0),
58  numLines_(0),
59  vboData_(0),
60  curTriPtr_(0),
61  vbo_(0)
62 {
63 
64  vertexDecl_.addElement(GL_FLOAT, 3, VERTEX_USAGE_POSITION);
65  vertexDecl_.addElement(GL_FLOAT, 3, VERTEX_USAGE_NORMAL);
66  vertexDecl_.addElement(GL_FLOAT, 2, VERTEX_USAGE_TEXCOORD);
67 }
68 
69 //------------------------------------------------------------------------
70 
71 GLPrimitive::~GLPrimitive()
72 {
73  if (vbo_)
74  glDeleteBuffers(1, &vbo_);
75 
76  delete[] vboData_;
77 }
78 
79 //------------------------------------------------------------------------
80 
81 void GLPrimitive::addTriangleToVBO(const ACG::Vec3f* _p, const ACG::Vec3f* _n, const ACG::Vec2f* _tex)
82 {
83  if (!numTris_ || vboDataInvalid_)
84  numTris_ = getNumTriangles();
85 
86  if (!numTris_)
87  return;
88 
89  assert(numLines_ == 0);
90 
91 
92  if (!vboData_)
93  vboData_ = new float[8 * 3 * numTris_];
94 
95  if (curTriPtr_ == numTris_)
96  return;
97 
98  float* pTri = &vboData_[0] + (curTriPtr_++) * 3 * 8;
99 
100  // copy triangle
101  for (int i = 0; i < 3; ++i) {
102  for (int k = 0; k < 3; ++k)
103  *(pTri++) = _p[i][k];
104 
105  for (int k = 0; k < 3; ++k)
106  *(pTri++) = _n[i][k];
107 
108  for (int k = 0; k < 2; ++k)
109  *(pTri++) = _tex[i][k];
110  }
111 }
112 
113 
114 void GLPrimitive::addLineToVBO( const ACG::Vec3f* _p, const ACG::Vec3f* _n, const ACG::Vec2f* _tex )
115 {
116  if (!numLines_ || vboDataInvalid_)
117  numLines_ = getNumLines();
118 
119  if (!numLines_)
120  return;
121 
122  assert(numTris_ == 0);
123 
124  if (!vboData_)
125  vboData_ = new float[8 * 2 * numLines_];
126 
127  if (curTriPtr_ == numLines_)
128  return;
129 
130  float* pLine = &vboData_[0] + (curTriPtr_++) * 2 * 8;
131 
132  // copy line segment
133  for (int i = 0; i < 2; ++i) {
134  for (int k = 0; k < 3; ++k)
135  *(pLine++) = _p[i][k];
136 
137  for (int k = 0; k < 3; ++k)
138  *(pLine++) = _n[i][k];
139 
140  for (int k = 0; k < 2; ++k)
141  *(pLine++) = _tex[i][k];
142  }
143 }
144 
145 
146 //------------------------------------------------------------------------
147 
148 void GLPrimitive::bindVBO()
149 {
150  if (checkVBO())
151  {
152  glBindBuffer(GL_ARRAY_BUFFER, vbo_);
153 
154  glVertexPointer(3, GL_FLOAT, 32, 0);
156  glEnableClientState(GL_VERTEX_ARRAY);
157 
158  glNormalPointer(GL_FLOAT, 32, (GLvoid*) 12);
160  glEnableClientState(GL_NORMAL_ARRAY);
161 
162  glClientActiveTexture(GL_TEXTURE0);
163  glTexCoordPointer(2, GL_FLOAT, 32, (GLvoid*) 24);
165  glEnableClientState(GL_TEXTURE_COORD_ARRAY);
166  }
167 }
168 
169 //------------------------------------------------------------------------
170 
171 
172 bool GLPrimitive::checkVBO()
173 {
174  // create vbo if not done yet
175  // update vbo data and upload to gpu if needed
176  // return false iff vbo empty
177 
178  const int bufSize = numTris_ ? numTris_ * 3 * 8 * 4 : numLines_ * 2 * 8 * 4;
179 
180  if (!vbo_) {
181  if (!vboData_ || (!numTris_ && !numLines_) || (numTris_ && numLines_))
182  return false;
183 
184  // create vbo
185  glGenBuffers(1, &vbo_);
186  glBindBuffer(GL_ARRAY_BUFFER, vbo_);
187  glBufferData(GL_ARRAY_BUFFER, bufSize, vboData_, GL_STATIC_DRAW);
188 
189  delete[] vboData_;
190  vboData_ = 0;
191  }
192 
193  if (vboDataInvalid_) {
194  updateVBOData();
195  glBindBuffer(GL_ARRAY_BUFFER, vbo_);
196  glBufferData(GL_ARRAY_BUFFER, bufSize, vboData_, GL_STATIC_DRAW);
197  vboDataInvalid_ = false;
198  }
199 
200  return true;
201 }
202 
203 //------------------------------------------------------------------------
204 
205 void GLPrimitive::unBindVBO()
206 {
207  glBindBuffer(GL_ARRAY_BUFFER, 0);
209  {
210  glDisableClientState(GL_VERTEX_ARRAY);
211  glDisableClientState(GL_NORMAL_ARRAY);
212  glDisableClientState(GL_TEXTURE_COORD_ARRAY);
213  }
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 
614  normal[0] = sin(beta);
615  normal[1] = cos(beta);
616  normal[2] = (bottomRadius_ - topRadius_);
617 
618  normal.normalize();
619  return normal;
620 }
621 
622 //------------------------------------------------------------------------
623 
624 void GLCone::addTriangle(int sl0, int st0, int sl1, int st1, int sl2, int st2)
625 {
626  ACG::Vec3f p[3];
627  ACG::Vec3f n[3];
628  ACG::Vec2f tex[3];
629 
630  p[0] = positionOnCone(sl0, st0);
631  p[1] = positionOnCone(sl1, st1);
632  p[2] = positionOnCone(sl2, st2);
633  if (normalOrientation_ == OUTSIDE) {
634  n[0] = normalOnCone(sl0, st0);
635  n[1] = normalOnCone(sl1, st1);
636  n[2] = normalOnCone(sl2, st2);
637  } else if (normalOrientation_ == INSIDE) {
638  n[0] = -normalOnCone(sl0, st0);
639  n[1] = -normalOnCone(sl1, st1);
640  n[2] = -normalOnCone(sl2, st2);
641  }
642  tex[0] = texCoordOnCone(sl0, st0);
643  tex[1] = texCoordOnCone(sl1, st1);
644  tex[2] = texCoordOnCone(sl2, st2);
645 
646  addTriangleToVBO(p, n, tex);
647 }
648 
649 //------------------------------------------------------------------------
650 
651 void GLCone::updateVBO()
652 {
653  for (int sl = 0; sl < slices_; ++sl) {
654  // top triangle:
655  if (topCap_) {
656  ACG::Vec3f p[3];
657  ACG::Vec3f n[3];
658  ACG::Vec2f tex[3];
659 
660  p[0] = ACG::Vec3f(0.0, 0.0, 1.0);
661  p[1] = positionOnCone(sl + 1, stacks_);
662  p[2] = positionOnCone(sl, stacks_);
663  if (normalOrientation_ == OUTSIDE) {
664  n[0] = ACG::Vec3f(0.0, 0.0, 1.0);
665  n[1] = ACG::Vec3f(0.0, 0.0, 1.0);
666  n[2] = ACG::Vec3f(0.0, 0.0, 1.0);
667  } else if (normalOrientation_ == INSIDE) {
668  n[0] = ACG::Vec3f(0.0, 0.0, -1.0);
669  n[1] = ACG::Vec3f(0.0, 0.0, -1.0);
670  n[2] = ACG::Vec3f(0.0, 0.0, -1.0);
671  }
672 
673  tex[0] = ACG::Vec2f(0.5, 0.5);
674  double beta = ((2.0 * M_PI) / slices_) * (sl + 1);
675  tex[1] = ACG::Vec2f(sin(beta), cos(beta));
676  beta = ((2.0 * M_PI) / slices_) * (sl);
677  tex[2] = ACG::Vec2f(sin(beta), cos(beta));
678 
679  addTriangleToVBO(p, n, tex);
680  }
681  // middle quads:
682  for (int st = 0; st < stacks_; ++st) {
683  addTriangle(sl, st, sl, st + 1, sl + 1, st);
684  addTriangle(sl + 1, st, sl, st + 1, sl + 1, st + 1);
685  }
686  // bottom triangle:
687  if (bottomCap_) {
688  ACG::Vec3f p[3];
689  ACG::Vec3f n[3];
690  ACG::Vec2f tex[3];
691 
692  p[0] = ACG::Vec3f(0.0, 0.0, 0.0);
693  p[1] = positionOnCone(sl, 0);
694  p[2] = positionOnCone(sl + 1, 0);
695  if (normalOrientation_ == OUTSIDE) {
696  n[0] = ACG::Vec3f(0.0, 0.0, -1.0);
697  n[1] = ACG::Vec3f(0.0, 0.0, -1.0);
698  n[2] = ACG::Vec3f(0.0, 0.0, -1.0);
699  } else if (normalOrientation_ == INSIDE) {
700  n[0] = ACG::Vec3f(0.0, 0.0, 1.0);
701  n[1] = ACG::Vec3f(0.0, 0.0, 1.0);
702  n[2] = ACG::Vec3f(0.0, 0.0, 1.0);
703  }
704 
705  tex[0] = ACG::Vec2f(0.5, 0.5);
706  double beta = ((2.0 * M_PI) / slices_) * (sl);
707  tex[1] = ACG::Vec2f(sin(beta), cos(beta));
708  beta = ((2.0 * M_PI) / slices_) * (sl + 1);
709  tex[2] = ACG::Vec2f(sin(beta), cos(beta));
710 
711  addTriangleToVBO(p, n, tex);
712  }
713  }
714 }
715 
716 //========================================================================
717 // GLCylinder
718 //========================================================================
719 
720 GLCylinder::GLCylinder(int _slices, int _stacks, float _radius, bool _bottomCap, bool _topCap) :
721  GLCone(_slices, _stacks, _radius, _radius, _bottomCap, _topCap)
722 {
723 }
724 
725 //========================================================================
726 // GLPartialDisk
727 //========================================================================
728 
737 GLPartialDisk::GLPartialDisk(int _slices, int _loops, float _innerRadius, float _outerRadius, float _startAngle, float _sweepAngle) :
738  slices_(_slices),
739  loops_(_loops),
740  innerRadius_(_innerRadius),
741  outerRadius_(_outerRadius),
742  startAngle_(_startAngle),
743  sweepAngle_(_sweepAngle)
744 {
745  updateVBO();
746 }
747 
748 //------------------------------------------------------------------------
749 
750 void GLPartialDisk::setInnerRadius(float _innerRadius) {
751  if (innerRadius_ != _innerRadius)
752  vboDataInvalid_ = true;
753  innerRadius_ = _innerRadius;
754 }
755 
756 //------------------------------------------------------------------------
757 
758 void GLPartialDisk::setOuterRadius(float _outerRadius) {
759  if (outerRadius_ != _outerRadius)
760  vboDataInvalid_ = true;
761  outerRadius_ = _outerRadius;
762 }
763 
764 //------------------------------------------------------------------------
765 
766 int GLPartialDisk::getNumTriangles() {
767  return slices_ * (loops_+1) * 2;
768 }
769 
770 //------------------------------------------------------------------------
771 
772 void GLPartialDisk::updateVBO() {
773  assert(slices_ >= 2);
774  assert(loops_ >= 1);
775  assert(outerRadius_ > 0.0f);
776  assert(innerRadius_ >= 0.0f);
777  assert(innerRadius_ < outerRadius_);
778 
779  if (sweepAngle_ < -360.0f)
780  sweepAngle_ = 360.0f;
781  if (sweepAngle_ > 360.0f)
782  sweepAngle_ = 360.0f;
783  if (sweepAngle_ < 0) {
784  startAngle_ += sweepAngle_;
785  sweepAngle_ = -sweepAngle_;
786  }
787 
788  float* sinCache = new float[slices_+1];
789  float* cosCache = new float[slices_+1];
790 
791  // precompute all sine and cosine that are needed
792  float angleOffsetRadian = startAngle_ * M_PI / 180.0f;
793  float sweepAngleRadian = sweepAngle_ * M_PI / 180.0f;
794  for (int i = 0; i < slices_+1; ++i) {
795  float angle = angleOffsetRadian + sweepAngleRadian * i/slices_;
796  sinCache[i] = sin(angle);
797  cosCache[i] = cos(angle);
798  }
799 
800  // iterate over loops (starting from the inner most) to generate triangles
801  float deltaRadius = outerRadius_ - innerRadius_;
802  for (int i = loops_+1; i > 0; --i) {
803 
804  // for each slice generate two triangles
805  for (int j = 0; j < slices_; ++j) {
806 
807  ACG::Vec3f p[3];
808  ACG::Vec3f n[3];
809  ACG::Vec2f tex[3];
810  ACG::Vec3f p2[3];
811  ACG::Vec3f n2[3];
812  ACG::Vec2f tex2[3];
813 
814  // radius of the loop nearer to the center of the disk
815  float innerRadius = outerRadius_ - deltaRadius * ((float) i / (loops_ + 1));
816  // radius of the loop further from the center of the disk
817  float outerRadius = outerRadius_ - deltaRadius * ((float) (i - 1) / (loops_ + 1));
818 
819  // first triangle:
820  // 1 2
821  //
822  // 0
823  // vertices
824  p[0] = ACG::Vec3f(innerRadius * sinCache[j], innerRadius * cosCache[j], 0.0f);
825  p[1] = ACG::Vec3f(outerRadius * sinCache[j], outerRadius * cosCache[j], 0.0f);
826  p[2] = ACG::Vec3f(outerRadius * sinCache[j+1], outerRadius * cosCache[j+1], 0.0f);
827  // normals
828  n[0] = ACG::Vec3f(0.0f, 0.0f, 1.0f);
829  n[1] = ACG::Vec3f(0.0f, 0.0f, 1.0f);
830  n[2] = ACG::Vec3f(0.0f, 0.0f, 1.0f);
831  // TODO: proper texture coordinates
832  tex[0] = ACG::Vec2f(0.0f, 0.0f);
833  tex[1] = ACG::Vec2f(0.0f, 0.0f);
834  tex[2] = ACG::Vec2f(0.0f, 0.0f);
835 
836  addTriangleToVBO(p, n, tex);
837 
838  // second triangle:
839  // x 1
840  //
841  // 0 2
842  // vertices
843  p2[0] = ACG::Vec3f(innerRadius * sinCache[j], innerRadius * cosCache[j], 0.0f);
844  p2[1] = ACG::Vec3f(outerRadius * sinCache[j+1], outerRadius * cosCache[j+1], 0.0f);
845  p2[2] = ACG::Vec3f(innerRadius * sinCache[j+1], innerRadius * cosCache[j+1], 0.0f);
846  // normals
847  n2[0] = ACG::Vec3f(0.0f, 0.0f, 1.0f);
848  n2[1] = ACG::Vec3f(0.0f, 0.0f, 1.0f);
849  n2[2] = ACG::Vec3f(0.0f, 0.0f, 1.0f);
850  // TODO: proper texture coordinates
851  tex2[0] = ACG::Vec2f(0.0f, 0.0f);
852  tex2[1] = ACG::Vec2f(0.0f, 0.0f);
853  tex2[2] = ACG::Vec2f(0.0f, 0.0f);
854 
855  addTriangleToVBO(p2, n2, tex2);
856 
857  }
858  }
859 
860  delete[] sinCache;
861  delete[] cosCache;
862 }
863 
864 //------------------------------------------------------------------------
865 
866 void GLPartialDisk::draw( GLState& _state, const ACG::Vec3f& _center, ACG::Vec3f _upDir) {
867  _state.push_modelview_matrix();
868 
869  // translate
870  _state.translate(ACG::Vec3d(_center));
871 
872  _upDir.normalize();
873 
874  // compute rotation matrix mAlign
875  // such that vBindDir rotates to _upDir
876  ACG::GLMatrixd mAlign;
877  mAlign.identity();
878 
879  ACG::Vec3f vBindDir(0.0f, 0.0f, 1.0f);
880 
881  ACG::Vec3f vRotAxis = OpenMesh::cross(_upDir, vBindDir);
882  vRotAxis.normalize();
883 
884  ACG::Vec3f vUp = OpenMesh::cross(_upDir, vRotAxis);
885 
886  // rotate
887  for (int i = 0; i < 3; ++i) {
888  mAlign(i, 0) = vRotAxis[i];
889  mAlign(i, 1) = vUp[i];
890  mAlign(i, 2) = _upDir[i];
891  }
892 
893  ACG::Vec3f vDelta = vBindDir - _upDir;
894  if ( fabsf(OpenMesh::dot(vDelta, vDelta)) < 1e-3f)
895  mAlign.identity();
896 
897  ACG::GLMatrixd mAlignInv(mAlign);
898  mAlignInv.invert();
899 
900  _state.mult_matrix(mAlign, mAlignInv);
901 
902  GLPrimitive::draw_primitive();
903 
904  _state.pop_modelview_matrix();
905 }
906 
907 //========================================================================
908 // GLDisk
909 //========================================================================
910 
917 GLDisk::GLDisk(int _slices, int _loops, float _innerRadius, float _outerRadius) :
918  GLPartialDisk(_slices, _loops, _innerRadius, _outerRadius, 0.0f, 360.0f)
919 {
920 }
921 
922 
923 //========================================================================
924 // GLBox
925 //========================================================================
926 
927 GLBox::GLBox()
928 {
929  updateVBO();
930 }
931 
932 GLBox::~GLBox()
933 {
934 }
935 
936 int GLBox::getNumTriangles()
937 {
938  return 12;
939 }
940 
941 //------------------------------------------------------------------------
942 
943 void GLBox::updateVBO()
944 {
945  static const Vec3f pos[8] =
946  {
947  Vec3f(-0.5f,-0.5f,0.5f), Vec3f(-0.5f,-0.5f,-0.5f), Vec3f(0.5f,-0.5f,-0.5f),
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)
950  };
951 
952  static const Vec3f norm[6] =
953  {
954  Vec3f(0.0f,-1.0f,0.0f), Vec3f(0.0f,1.0f,0.0f), Vec3f(0.0f,0.0f,1.0f),
955  Vec3f(1.0f,0.0f,0.0f), Vec3f(0.0f,0.0f,-1.0f), Vec3f(-1.0f,0.0f,0.0f)
956  };
957 
958  static const Vec2f texc[4] =
959  {
960  Vec2f(1.0f,0.0f), Vec2f(1.0f,1.0f), Vec2f(0.0f,1.0f), Vec2f(0.0f,0.0f)
961  };
962 
963  // tri: p,p,p ,n,n,n ,t,t,t
964  static const int tris[12][9] =
965  {
966  {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},
967  {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},
968  {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},
969  {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}
970  };
971 
972  for (int i = 0; i < 12; ++i)
973  {
974  Vec3f triPos[3] = { pos[tris[i][0]], pos[tris[i][1]], pos[tris[i][2]] };
975  Vec3f triNorm[3] = { norm[tris[i][3]], norm[tris[i][4]], norm[tris[i][5]] };
976  Vec2f triTexc[3] = { texc[tris[i][6]], texc[tris[i][7]], texc[tris[i][8]] };
977 
978  addTriangleToVBO(triPos, triNorm, triTexc);
979  }
980 }
981 
982 //------------------------------------------------------------------------
983 
984 GLLineBox::GLLineBox()
985 {
986  updateVBO();
987 }
988 
989 GLLineBox::~GLLineBox()
990 {
991 }
992 
993 //------------------------------------------------------------------------
994 
995 int GLLineBox::getNumTriangles()
996 {
997  return 0;
998 }
999 
1000 int GLLineBox::getNumLines()
1001 {
1002  return 12;
1003 }
1004 
1005 //------------------------------------------------------------------------
1006 
1007 void GLLineBox::updateVBO()
1008 {
1009  static const Vec3f pos[8] =
1010  {
1011  Vec3f(-0.5f,-0.5f,0.5f), Vec3f(-0.5f,-0.5f,-0.5f), Vec3f(0.5f,-0.5f,-0.5f),
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)
1014  };
1015 
1016  static const Vec3f norm[6] =
1017  {
1018  Vec3f(0.0f,-1.0f,0.0f), Vec3f(0.0f,1.0f,0.0f), Vec3f(0.0f,0.0f,1.0f),
1019  Vec3f(1.0f,0.0f,0.0f), Vec3f(0.0f,0.0f,-1.0f), Vec3f(-1.0f,0.0f,0.0f)
1020  };
1021 
1022  static const Vec2f texc[4] =
1023  {
1024  Vec2f(1.0f,0.0f), Vec2f(1.0f,1.0f), Vec2f(0.0f,1.0f), Vec2f(0.0f,0.0f)
1025  };
1026 
1027  // line: p,p ,n,n ,t,t
1028  static const int lines[12][6] =
1029  {
1030  {1,2, 0,0, 0,3}, {0,3, 0,0, 0,3}, {4,5, 0,0, 0,3}, {7,6, 0,0, 0,3},
1031  {1,7, 0,0, 0,3}, {0,4, 0,0, 0,3}, {2,6, 0,0, 0,3}, {3,5, 0,0, 0,3},
1032  {1,0, 0,0, 0,3}, {2,3, 0,0, 0,3}, {7,4, 0,0, 0,3}, {6,5, 0,0, 0,3}
1033  };
1034 
1035  for (int i = 0; i < 12; ++i)
1036  {
1037  Vec3f p[2] = { pos[lines[i][0]], pos[lines[i][1]]};
1038  Vec3f n[2] = { norm[lines[i][2]], norm[lines[i][3]]};
1039  Vec2f t[2] = { texc[lines[i][4]], texc[lines[i][5]]};
1040 
1041  addLineToVBO(p, n, t);
1042  }
1043 }
1044 
1045 //------------------------------------------------------------------------
1046 
1047 //------------------------------------------------------------------------
1048 
1049 GLDodecahedron::GLDodecahedron()
1050 {
1051  updateVBO();
1052 }
1053 
1054 GLDodecahedron::~GLDodecahedron()
1055 {
1056 }
1057 
1058 //------------------------------------------------------------------------
1059 
1060 int GLDodecahedron::getNumTriangles()
1061 {
1062  return 36;
1063 }
1064 
1065 //------------------------------------------------------------------------
1066 
1067 void GLDodecahedron::updateVBO()
1068 {
1069  static const Vec3f pos[20] =
1070  {Vec3f( 1 , 1 , 1 ),
1071  Vec3f( 1 , 1 , -1 ),
1072  Vec3f( 1 , -1 , 1 ),
1073  Vec3f( 1 , -1 , -1 ),
1074  Vec3f( -1 , 1 , 1 ),
1075  Vec3f( -1 , 1 , -1 ),
1076  Vec3f( -1 , -1 , 1 ),
1077  Vec3f( -1 , -1 , -1 ),
1078  Vec3f( 0 , 0.618034 , 1.61803 ),
1079  Vec3f( 0 , 0.618034 , -1.61803 ),
1080  Vec3f( 0 , -0.618034 , 1.61803 ),
1081  Vec3f( 0 , -0.618034 , -1.61803 ),
1082  Vec3f( 0.618034 , 1.61803 , 0 ),
1083  Vec3f( 0.618034 , -1.61803 , 0 ),
1084  Vec3f( -0.618034 , 1.61803 , 0 ),
1085  Vec3f( -0.618034 , -1.61803 , 0 ),
1086  Vec3f( 1.61803 , 0 , 0.618034 ),
1087  Vec3f( 1.61803 , 0 , -0.618034 ),
1088  Vec3f( -1.61803 , 0 , 0.618034 ),
1089  Vec3f( -1.61803 , 0 , -0.618034 )
1090  };
1091 
1092  static const Vec3f norm[20] =
1093  {
1094  Vec3f( 0.57735 , 0.57735 , 0.57735 ),
1095  Vec3f( 0.57735 , 0.57735 , -0.57735 ),
1096  Vec3f( 0.57735 , -0.57735 , 0.57735 ),
1097  Vec3f( 0.57735 , -0.57735 , -0.57735 ),
1098  Vec3f( -0.57735 , 0.57735 , 0.57735 ),
1099  Vec3f( -0.57735 , 0.57735 , -0.57735 ),
1100  Vec3f( -0.57735 , -0.57735 , 0.57735 ),
1101  Vec3f( -0.57735 , -0.57735 , -0.57735 ),
1102  Vec3f( 0 , 0.356822 , 0.934172 ),
1103  Vec3f( 0 , 0.356822 , -0.934172 ),
1104  Vec3f( 0 , -0.356822 , 0.934172 ),
1105  Vec3f( 0 , -0.356822 , -0.934172 ),
1106  Vec3f( 0.356822 , 0.934172 , 0 ),
1107  Vec3f( 0.356822 , -0.934172 , 0 ),
1108  Vec3f( -0.356822 , 0.934172 , 0 ),
1109  Vec3f( -0.356822 , -0.934172 , 0 ),
1110  Vec3f( 0.934172 , 0 , 0.356822 ),
1111  Vec3f( 0.934172 , 0 , -0.356822 ),
1112  Vec3f( -0.934172 , 0 , 0.356822 ),
1113  Vec3f( -0.934172 , 0 , -0.356822 )
1114  };
1115 
1116  static const Vec2f texc[20] =
1117  {
1118  Vec2f( 1, 1),
1119  Vec2f( 1, 1),
1120  Vec2f( 1, 1),
1121  Vec2f( 1, 1),
1122  Vec2f( 1, 1),
1123  Vec2f( 1, 1),
1124  Vec2f( 1, 1),
1125  Vec2f( 1, 1),
1126  Vec2f( 1, 1),
1127  Vec2f( 1, 1),
1128  Vec2f( 1, 1),
1129  Vec2f( 1, 1),
1130  Vec2f( 1, 1),
1131  Vec2f( 1, 1),
1132  Vec2f( 1, 1),
1133  Vec2f( 1, 1),
1134  Vec2f( 1, 1),
1135  Vec2f( 1, 1),
1136  Vec2f( 1, 1),
1137  Vec2f( 1, 1)
1138  };
1139 
1140  // not the usual p,p,p ,n,n,n ,t,t,t
1141  // i extracted those from an obj file so its:
1142  // tri: p,t,n ,p,t,n ,p,t,n
1143  static const int tris[36][9] =
1144  {
1145  { 20,20,20, 19,19,19, 5,5,5 },
1146  { 12,12,12, 8,8,8, 20,20,20 },
1147  { 14,14,14, 3,3,3, 11,11,11 },
1148  { 17,17,17, 18,18,18, 2,2,2 },
1149  { 11,11,11, 3,3,3, 17,17,17 },
1150  { 14,14,14, 4,4,4, 18,18,18 },
1151  { 16,16,16, 8,8,8, 12,12,12 },
1152  { 7,7,7, 19,19,19, 20,20,20 },
1153  { 7,7,7, 11,11,11, 9,9,9 },
1154  { 1,1,1, 13,13,13, 15,15,15 },
1155  { 2,2,2, 10,10,10, 6,6,6 },
1156  { 18,18,18, 4,4,4, 12,12,12 },
1157  { 15,15,15, 6,6,6, 5,5,5 },
1158  { 6,6,6, 20,20,20, 5,5,5 },
1159  { 6,6,6, 10,10,10, 20,20,20 },
1160  { 10,10,10, 12,12,12, 20,20,20 },
1161  { 7,7,7, 16,16,16, 11,11,11 },
1162  { 16,16,16, 14,14,14, 11,11,11 },
1163  { 13,13,13, 1,1,1, 2,2,2 },
1164  { 1,1,1, 17,17,17, 2,2,2 },
1165  { 1,1,1, 9,9,9, 17,17,17 },
1166  { 9,9,9, 11,11,11, 17,17,17 },
1167  { 17,17,17, 3,3,3, 18,18,18 },
1168  { 3,3,3, 14,14,14, 18,18,18 },
1169  { 4,4,4, 14,14,14, 12,12,12 },
1170  { 14,14,14, 16,16,16, 12,12,12 },
1171  { 8,8,8, 16,16,16, 20,20,20 },
1172  { 16,16,16, 7,7,7, 20,20,20 },
1173  { 5,5,5, 19,19,19, 9,9,9 },
1174  { 19,19,19, 7,7,7, 9,9,9 },
1175  { 5,5,5, 9,9,9, 15,15,15 },
1176  { 9,9,9, 1,1,1, 15,15,15 },
1177  { 15,15,15, 13,13,13, 6,6,6 },
1178  { 13,13,13, 2,2,2, 6,6,6 },
1179  { 10,10,10, 2,2,2, 12,12,12 },
1180  { 2,2,2, 18,18,18, 12,12,12 }
1181  };
1182 
1183  //-1 since the objindices start at 1
1184  for (int i = 0; i < 36; ++i)
1185  {
1186  Vec3f p[3] = { pos[tris[i][0]-1], pos[tris[i][3]-1], pos[tris[i][6]-1]};
1187  Vec3f n[3] = { norm[tris[i][2]-1], norm[tris[i][5]-1], norm[tris[i][8]-1]};
1188  Vec2f t[3] = { texc[tris[i][1]-1], texc[tris[i][4]-1], texc[tris[i][7]-1]};
1189 
1190  addTriangleToVBO(p, n, t);
1191  }
1192 }
1193 
1194 //------------------------------------------------------------------------
1195 
1196 GLIcosahedron::GLIcosahedron()
1197 {
1198  updateVBO();
1199 }
1200 
1201 GLIcosahedron::~GLIcosahedron()
1202 {
1203 }
1204 
1205 //------------------------------------------------------------------------
1206 
1207 int GLIcosahedron::getNumTriangles()
1208 {
1209  return 20;
1210 }
1211 
1212 //------------------------------------------------------------------------
1213 
1214 void GLIcosahedron::updateVBO()
1215 {
1216  static const Vec3f pos[12] =
1217  {
1218  Vec3f( 0 , -1 , -1.61803),
1219  Vec3f( 0 , 1 , -1.61803),
1220  Vec3f( 0 , 1 , 1.61803 ),
1221  Vec3f( 0 , -1 , 1.61803 ),
1222  Vec3f( -1 , -1.61803, 0 ),
1223  Vec3f( 1 , -1.61803, 0 ),
1224  Vec3f( 1 , 1.61803 , 0 ),
1225  Vec3f( -1 , 1.61803 , 0 ),
1226  Vec3f( -1.61803 , 0 , -1 ),
1227  Vec3f( -1.61803 , 0 , 1 ),
1228  Vec3f( 1.61803 , 0 , 1 ),
1229  Vec3f( 1.61803 , 0 , -1 )
1230  };
1231 
1232  static const Vec3f norm[12] =
1233  {
1234  Vec3f( 0 , -0.525731 , -0.850651 ),
1235  Vec3f( 2.79423e-17, 0.525731 , -0.850651 ),
1236  Vec3f( 0 , 0.525731 , 0.850651 ),
1237  Vec3f( 2.79423e-17, -0.525731 , 0.850651 ),
1238  Vec3f( -0.525731 , -0.850651 , 0 ),
1239  Vec3f( 0.525731 , -0.850651 , 2.79423e-17 ),
1240  Vec3f( 0.525731 , 0.850651 , 0 ),
1241  Vec3f( -0.525731 , 0.850651 , 0 ),
1242  Vec3f( -0.850651 , 2.79423e-17, 0.525731 ),
1243  Vec3f( 0.850651 , 0 , 0.525731 ),
1244  Vec3f( -0.850651 , 0 , -0.525731 ),
1245  Vec3f( 0.850651 , 2.79423e-17, -0.525731 )
1246  };
1247 
1248  static const Vec2f texc[12] =
1249  {
1250  Vec2f( 0, 0),
1251  Vec2f( 0, 0),
1252  Vec2f( 0, 0),
1253  Vec2f( 0, 0),
1254  Vec2f( 0, 0),
1255  Vec2f( 0, 0),
1256  Vec2f( 0, 0),
1257  Vec2f( 0, 0),
1258  Vec2f( 0, 0),
1259  Vec2f( 0, 0),
1260  Vec2f( 0, 0),
1261  Vec2f( 0, 0)
1262  };
1263 
1264  // not the usual p,p,p ,n,n,n ,t,t,t
1265  // i extracted those from an obj file so its:
1266  // tri: p,t,n ,p,t,n ,p,t,n
1267  static const int tris[20][9] =
1268  {
1269  { 3,3,3, 7,7,7, 8,8,8, },
1270  { 8,8,8, 7,7,7, 2,2,2, },
1271  { 12,12,12, 1,1,1, 2,2,2, },
1272  { 1,1,1, 9,9,9, 2,2,2, },
1273  { 5,5,5, 10,10,10, 9,9,9, },
1274  { 9,9,9, 10,10,10, 8,8,8, },
1275  { 10,10,10, 4,4,4, 3,3,3, },
1276  { 11,11,1,3,3,3, 4,4,4, },
1277  { 6,6,6, 12,12,12, 11,11,1, },
1278  { 12,12,12, 7,7,7, 11,11,1, },
1279  { 1,1,1, 6,6,6, 5,5,5, },
1280  { 6,6,6, 4,4,4, 5,5,5, },
1281  { 7,7,7, 3,3,3, 11,11,1, },
1282  { 7,7,7, 12,12,12, 2,2,2, },
1283  { 2,2,2, 9,9,9, 8,8,8, },
1284  { 10,10,10, 3,3,3, 8,8,8, },
1285  { 4,4,4, 6,6,6, 11,11,1, },
1286  { 1,1,1, 12,12,12, 6,6,6, },
1287  { 4,4,4, 10,10,10, 5,5,5, },
1288  { 1,1,1, 5,5,5, 9,9,9, }
1289  };
1290 
1291  //-1 since the objindices start at 1
1292  for (int i = 0; i < 20; ++i)
1293  {
1294  Vec3f p[3] = { pos[tris[i][0]-1], pos[tris[i][3]-1], pos[tris[i][6]-1]};
1295  Vec3f n[3] = { norm[tris[i][2]-1], norm[tris[i][5]-1], norm[tris[i][8]-1]};
1296  Vec2f t[3] = { texc[tris[i][1]-1], texc[tris[i][4]-1], texc[tris[i][7]-1]};
1297 
1298  addTriangleToVBO(p, n, t);
1299  }
1300 }
1301 
1302 //------------------------------------------------------------------------
1303 
1304 GLOctahedron::GLOctahedron()
1305 {
1306  updateVBO();
1307 }
1308 
1309 GLOctahedron::~GLOctahedron()
1310 {
1311 }
1312 
1313 //------------------------------------------------------------------------
1314 
1315 int GLOctahedron::getNumTriangles()
1316 {
1317  return 8;
1318 }
1319 
1320 //------------------------------------------------------------------------
1321 
1322 void GLOctahedron::updateVBO()
1323 {
1324  static const Vec3f pos[6] =
1325  {
1326  Vec3f( -1.41421 , 0 , 0 ),
1327  Vec3f( 0 , -1.41421, 0 ),
1328  Vec3f( 1.41421 , 0 , 0 ),
1329  Vec3f( 0 , 1.41421 , 0 ),
1330  Vec3f( 0 , 0 , 1.41421 ),
1331  Vec3f( 0 , 0 , -1.41421)
1332  };
1333 
1334  static const Vec3f norm[6] =
1335  {
1336  Vec3f(-1, 0 , 0 ),
1337  Vec3f(0 , -1, 0 ),
1338  Vec3f(1 , 0 , 0 ),
1339  Vec3f(0 , 1 , 0 ),
1340  Vec3f(0 , 0 , 1 ),
1341  Vec3f(0 , 0 , -1)
1342  };
1343 
1344  static const Vec2f texc[6] =
1345  {
1346  Vec2f( 0, 0),
1347  Vec2f( 0, 0),
1348  Vec2f( 0, 0),
1349  Vec2f( 0, 0),
1350  Vec2f( 0, 0),
1351  Vec2f( 0, 0)
1352  };
1353 
1354  // not the usual p,p,p ,n,n,n ,t,t,t
1355  // i extracted those from an obj file so its:
1356  // tri: p,t,n ,p,t,n ,p,t,n
1357  static const int tris[8][9] =
1358  {
1359  { 1,1,1, 2,2,2, 5,5,5 },
1360  { 2,2,2, 3,3,3, 5,5,5 },
1361  { 3,3,3, 4,4,4, 5,5,5 },
1362  { 1,1,1, 5,5,5, 4,4,4 },
1363  { 6,6,6, 2,2,2, 1,1,1 },
1364  { 6,6,6, 3,3,3, 2,2,2 },
1365  { 6,6,6, 4,4,4, 3,3,3 },
1366  { 6,6,6, 1,1,1, 4,4,4 }
1367  };
1368 
1369  //-1 since the objindices start at 1
1370  for (int i = 0; i < 8; ++i)
1371  {
1372  Vec3f p[3] = { pos[tris[i][0]-1], pos[tris[i][3]-1], pos[tris[i][6]-1]};
1373  Vec3f n[3] = { norm[tris[i][2]-1], norm[tris[i][5]-1], norm[tris[i][8]-1]};
1374  Vec2f t[3] = { texc[tris[i][1]-1], texc[tris[i][4]-1], texc[tris[i][7]-1]};
1375 
1376  addTriangleToVBO(p, n, t);
1377  }
1378 }
1379 
1380 //------------------------------------------------------------------------
1381 
1382 GLTetrahedron::GLTetrahedron()
1383 {
1384  updateVBO();
1385 }
1386 
1387 GLTetrahedron::~GLTetrahedron()
1388 {
1389 }
1390 
1391 //------------------------------------------------------------------------
1392 
1393 int GLTetrahedron::getNumTriangles()
1394 {
1395  return 4;
1396 }
1397 
1398 //------------------------------------------------------------------------
1399 
1400 void GLTetrahedron::updateVBO()
1401 {
1402  static const Vec3f pos[4] =
1403  {
1404  Vec3f( -1, -1, 1 ),
1405  Vec3f( 1 , 1 , 1 ),
1406  Vec3f( -1, 1 , -1 ),
1407  Vec3f( 1 , -1, -1 )
1408  };
1409 
1410  static const Vec3f norm[4] =
1411  {
1412  Vec3f( -0.57735, -0.57735, 0.57735 ),
1413  Vec3f( 0.57735 , 0.57735 , 0.57735 ),
1414  Vec3f( -0.57735, 0.57735 , -0.57735 ),
1415  Vec3f( 0.57735 , -0.57735, -0.57735 )
1416  };
1417 
1418  static const Vec2f texc[4] =
1419  {
1420  Vec2f( 0, 0),
1421  Vec2f( 0, 0),
1422  Vec2f( 0, 0),
1423  Vec2f( 0, 0)
1424  };
1425 
1426  // not the usual p,p,p ,n,n,n ,t,t,t
1427  // i extracted those from an obj file so its:
1428  // tri: p,t,n ,p,t,n ,p,t,n
1429  static const int tris[4][9] =
1430  {
1431  { 1, 1, 1, 2, 2, 2, 3, 3, 3 },
1432  { 1, 1, 1, 3, 3, 3, 4, 4, 4 },
1433  { 3, 3, 3, 2, 2, 2, 4, 4, 4 },
1434  { 4, 4, 4, 2, 2, 2, 1, 1, 1 }
1435  };
1436 
1437  //-1 since the objindices start at 1
1438  for (int i = 0; i < 4; ++i)
1439  {
1440  Vec3f p[3] = { pos[tris[i][0]-1], pos[tris[i][3]-1], pos[tris[i][6]-1]};
1441  Vec3f n[3] = { norm[tris[i][2]-1], norm[tris[i][5]-1], norm[tris[i][8]-1]};
1442  Vec2f t[3] = { texc[tris[i][1]-1], texc[tris[i][4]-1], texc[tris[i][7]-1]};
1443 
1444  addTriangleToVBO(p, n, t);
1445  }
1446 }
1447 
1448 //------------------------------------------------------------------------
1449 GLTorus::GLTorus(GLdouble innerRadius,
1450  GLdouble outerRadius,
1451  GLint nsides, GLint rings):
1452  rings_(rings),
1453  nsides_(nsides),
1454  innerRadius_(innerRadius),
1455  outerRadius_(outerRadius)
1456 {
1457 
1458  updateVBO();
1459 }
1460 
1461 GLTorus::~GLTorus()
1462 {
1463 }
1464 
1465 //------------------------------------------------------------------------
1466 
1467 int GLTorus::getNumTriangles()
1468 {
1469  return rings_*nsides_*2;
1470 }
1471 
1472 //------------------------------------------------------------------------
1473 
1474 void GLTorus::updateVBO()
1475 {
1476  // build the Torus in two steps.
1477  // First build a unit Ring in XZ plane.
1478  // Then copy and rotate the ring around z axis to form a torus.
1479  //
1480  // create faces and normals + texcoordinates.
1481  // Inner seam is top/bottom of texture
1482  std::vector<Vec3f> points;
1483  std::vector<Vec3f> normals;
1484  std::vector<Vec2f> texCoords;
1485  std::vector<Vec3f> unitRing;
1486 
1487  float ringSegmentAngle = 2 * M_PI / nsides_;
1488  float torusSegmentAngle = 2 * M_PI / rings_;
1489 
1490  // generate a unit ring with n sides
1491  for (int i = 0 ; i < nsides_ ; ++i)
1492  {
1493  Vec3f ringPoint = Vec3f(cos(ringSegmentAngle * i),0.0f,sin(ringSegmentAngle *i));
1494  unitRing.push_back(ringPoint);
1496  }
1497 
1498  for(int j = 0; j < rings_ ; ++j)
1499  {
1500  Vec3f torusPoint;
1501  int side = 0;
1502  for(Vec3f point : unitRing)
1503  {
1504  //scale the unit Ring
1505  torusPoint = point * (1.f/innerRadius_);
1506  //translate the unit Ring
1507  torusPoint +=Vec3f(outerRadius_ + innerRadius_,0,0);
1508  //rotate the translated ring around the z axis
1509  Vec3f pointOnTorus = Vec3f(torusPoint[0] * cos(j*torusSegmentAngle) + torusPoint[1] * sin(j*torusSegmentAngle),
1510  torusPoint[0] * -sin(j*torusSegmentAngle) + torusPoint[1] * cos(j*torusSegmentAngle),
1511  torusPoint[2]);
1512 
1513  points.push_back(pointOnTorus);
1514 
1515  //the normal does not have to be translated or scaled
1516  Vec3f normalOnTorus = Vec3f(point[0] * cos(j*torusSegmentAngle) + point[1] * sin(j*torusSegmentAngle),
1517  point[0] * -sin(j*torusSegmentAngle) + point[1] * cos(j*torusSegmentAngle),
1518  point[2]);
1519  // probably not necessary as we are working with the unit circle
1520  normalOnTorus.normalize();
1521  normals.push_back(normalOnTorus);
1522 
1523  // texcoords are a simple uv unwrap of the torus cut open.
1524  // j/rings_ is directly the u component
1525  // the ring segment gives us the v component
1526  texCoords.push_back(Vec2f(j/rings_,side/nsides_));
1527  ++side;
1528  }
1529  }
1530 
1531  // points are now stored one ring after the other in the points vector.
1532  // creating a triangle is fairly easy adding nsides_ to the current index gives the same point on the next ring.
1533  // create triangles as point on ring -> same point on next ring -> next point on next ring.
1534  int end = rings_*nsides_;
1535  int segmentOffset = nsides_;
1536  int oddIndex = 0;
1537  for(int i = 0 ; i < end ; ++i)
1538  {
1539  if((i+1) % nsides_ == 0)
1540  {
1541  segmentOffset = 0;
1542  oddIndex = -nsides_;
1543  }
1544  else
1545  {
1546  segmentOffset = nsides_;
1547  oddIndex = 0;
1548  }
1549  // first face (lower left triangle)
1550  Vec3f p[3] = { points[i] , points[(i+nsides_)%end] , points[(i+segmentOffset+1)%end] };
1551  Vec3f n[3] = { normals[i] , normals[(i+nsides_)%end] , normals[(i+segmentOffset+1)%end] };
1552  Vec2f t[3] = { texCoords[i] , texCoords[(i+nsides_)%end] , texCoords[(i+segmentOffset+1)%end] };
1553  addTriangleToVBO(p, n, t);
1554  // second face (upper right triangle)
1555  Vec3f p2[3] = { points[(i+1 + oddIndex)%end] , points[(i)%end] , points[(i+segmentOffset+1)%end] };
1556  Vec3f n2[3] = { normals[(i+1 + oddIndex)%end] , normals[(i)%end] , normals[(i+segmentOffset+1)%end] };
1557  Vec2f t2[3] = { texCoords[(i+1 + oddIndex)%end] , texCoords[(i)%end], texCoords[(i+segmentOffset+1)%end] };
1558  addTriangleToVBO(p2, n2, t2);
1559  }
1560 }
1561 
1562 //------------------------------------------------------------------------
1563 }
bool invert()
matrix inversion (returns true on success)
Namespace providing different geometric functions concerning angles.
osg::Vec3f cross(const osg::Vec3f &_v1, const osg::Vec3f &_v2)
Adapter for osg vector member computing a scalar product.
void push_modelview_matrix()
push modelview matrix
Definition: GLState.cc:1010
VectorT< float, 3 > Vec3f
Definition: VectorT.hh:119
GLDisk(int _slices, int _loops, float _innerRadius, float _outerRadius)
void translate(double _x, double _y, double _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
translate by (_x, _y, _z)
Definition: GLState.cc:533
auto normalize() -> decltype(*this/=std::declval< VectorT< S, DIM >>().norm())
Definition: Vector11T.hh:429
void compatibilityProfile(bool _enableCoreProfile)
Store opengl core profile setting.
Definition: gl.cc:166
GLSL program class.
Definition: GLSLShader.hh:211
osg::Vec3f::ValueType dot(const osg::Vec3f &_v1, const osg::Vec3f &_v2)
Adapter for osg vector member computing a scalar product.
VectorT< float, 2 > Vec2f
Definition: VectorT.hh:102
void mult_matrix(const GLMatrixd &_m, const GLMatrixd &_inv_m, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
multiply by a given transformation matrix
Definition: GLState.cc:614
void scale(Scalar _x, Scalar _y, Scalar _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
multiply self with scaling matrix (x,y,z)
GLPartialDisk(int _slices, int _loops, float _innerRadius, float _outerRadius, float _startAngle, float _sweepAngle)
void pop_modelview_matrix()
pop modelview matrix
Definition: GLState.cc:1026
void identity()
setup an identity matrix