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
48namespace ACG {
49
50//========================================================================
51// GLPrimitive base class
52//========================================================================
53
54GLPrimitive::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
71GLPrimitive::~GLPrimitive()
72{
73 if (vbo_)
74 glDeleteBuffers(1, &vbo_);
75
76 delete[] vboData_;
77}
78
79//------------------------------------------------------------------------
80
81void 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
114void 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
148void 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
172bool 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
205void 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
218void 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
232void 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
251void 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
269void GLPrimitive::updateVBOData() {
270 curTriPtr_ = 0;
271
272 if (vboData_) {
273 delete[] vboData_;
274 vboData_ = 0;
275 }
276
277 updateVBO();
278}
279
280//------------------------------------------------------------------------
281
282unsigned int GLPrimitive::getVBO()
283{
284 return checkVBO() ? vbo_ : 0;
285}
286
287const VertexDeclaration* GLPrimitive::getVertexDecl() const
288{
289 return &vertexDecl_;
290}
291
292//========================================================================
293// GLSphere
294//========================================================================
295
296
297
298GLSphere::GLSphere(int _slices, int _stacks) :
299 slices_(_slices),
300 stacks_(_stacks)
301{
302 updateVBO();
303}
304
305//------------------------------------------------------------------------
306
307GLSphere::~GLSphere()
308{
309
310}
311
312//------------------------------------------------------------------------
313
314void 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
328void 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
341int GLSphere::getNumTriangles()
342{
343 return 2 * slices_ + (stacks_ - 2) * slices_ * 2;
344}
345
346//------------------------------------------------------------------------
347
348void 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
370void 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
391ACG::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
408ACG::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
423GLCone::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
436GLCone::~GLCone()
437{
438
439}
440
441//------------------------------------------------------------------------
442
443void GLCone::setBottomRadius(float _bottomRadius) {
444 if (bottomRadius_ != _bottomRadius)
445 vboDataInvalid_ = true;
446 bottomRadius_ = _bottomRadius;
447}
448
449//------------------------------------------------------------------------
450
451void GLCone::setTopRadius(float _topRadius) {
452 if (topRadius_ != _topRadius)
453 vboDataInvalid_ = true;
454 topRadius_ = _topRadius;
455}
456
457//------------------------------------------------------------------------
458
459void GLCone::setNormalOrientation(NormalOrientation orientation) {
460 if (normalOrientation_ != orientation)
461 vboDataInvalid_ = true;
462 normalOrientation_ = orientation;
463}
464
465//------------------------------------------------------------------------
466
467void 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
517void 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
564int 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
578ACG::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
595ACG::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
607ACG::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
624void 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
651void 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
720GLCylinder::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
737GLPartialDisk::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
750void GLPartialDisk::setInnerRadius(float _innerRadius) {
751 if (innerRadius_ != _innerRadius)
752 vboDataInvalid_ = true;
753 innerRadius_ = _innerRadius;
754}
755
756//------------------------------------------------------------------------
757
758void GLPartialDisk::setOuterRadius(float _outerRadius) {
759 if (outerRadius_ != _outerRadius)
760 vboDataInvalid_ = true;
761 outerRadius_ = _outerRadius;
762}
763
764//------------------------------------------------------------------------
765
766int GLPartialDisk::getNumTriangles() {
767 return slices_ * (loops_+1) * 2;
768}
769
770//------------------------------------------------------------------------
771
772void 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
866void 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
917GLDisk::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
927GLBox::GLBox()
928{
929 updateVBO();
930}
931
932GLBox::~GLBox()
933{
934}
935
936int GLBox::getNumTriangles()
937{
938 return 12;
939}
940
941//------------------------------------------------------------------------
942
943void 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
984GLLineBox::GLLineBox()
985{
986 updateVBO();
987}
988
989GLLineBox::~GLLineBox()
990{
991}
992
993//------------------------------------------------------------------------
994
995int GLLineBox::getNumTriangles()
996{
997 return 0;
998}
999
1000int GLLineBox::getNumLines()
1001{
1002 return 12;
1003}
1004
1005//------------------------------------------------------------------------
1006
1007void 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
1049GLDodecahedron::GLDodecahedron()
1050{
1051 updateVBO();
1052}
1053
1054GLDodecahedron::~GLDodecahedron()
1055{
1056}
1057
1058//------------------------------------------------------------------------
1059
1060int GLDodecahedron::getNumTriangles()
1061{
1062 return 36;
1063}
1064
1065//------------------------------------------------------------------------
1066
1067void 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
1196GLIcosahedron::GLIcosahedron()
1197{
1198 updateVBO();
1199}
1200
1201GLIcosahedron::~GLIcosahedron()
1202{
1203}
1204
1205//------------------------------------------------------------------------
1206
1207int GLIcosahedron::getNumTriangles()
1208{
1209 return 20;
1210}
1211
1212//------------------------------------------------------------------------
1213
1214void 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
1304GLOctahedron::GLOctahedron()
1305{
1306 updateVBO();
1307}
1308
1309GLOctahedron::~GLOctahedron()
1310{
1311}
1312
1313//------------------------------------------------------------------------
1314
1315int GLOctahedron::getNumTriangles()
1316{
1317 return 8;
1318}
1319
1320//------------------------------------------------------------------------
1321
1322void 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
1382GLTetrahedron::GLTetrahedron()
1383{
1384 updateVBO();
1385}
1386
1387GLTetrahedron::~GLTetrahedron()
1388{
1389}
1390
1391//------------------------------------------------------------------------
1392
1393int GLTetrahedron::getNumTriangles()
1394{
1395 return 4;
1396}
1397
1398//------------------------------------------------------------------------
1399
1400void 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//------------------------------------------------------------------------
1449GLTorus::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
1461GLTorus::~GLTorus()
1462{
1463}
1464
1465//------------------------------------------------------------------------
1466
1467int GLTorus::getNumTriangles()
1468{
1469 return rings_*nsides_*2;
1470}
1471
1472//------------------------------------------------------------------------
1473
1474void 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;
1536 int oddIndex;
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}
GLDisk(int _slices, int _loops, float _innerRadius, float _outerRadius)
void scale(Scalar _x, Scalar _y, Scalar _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
multiply self with scaling matrix (x,y,z)
void identity()
setup an identity matrix
GLSL program class.
Definition: GLSLShader.hh:211
auto normalize() -> decltype(*this/=std::declval< VectorT< S, DIM > >().norm())
Definition: Vector11T.hh:454
Namespace providing different geometric functions concerning angles.
VectorT< float, 3 > Vec3f
Definition: VectorT.hh:119
VectorT< float, 2 > Vec2f
Definition: VectorT.hh:102
void compatibilityProfile(bool _enableCoreProfile)
Store opengl core profile setting.
Definition: gl.cc:166
osg::Vec3f::ValueType dot(const osg::Vec3f &_v1, const osg::Vec3f &_v2)
Adapter for osg vector member computing a scalar product.
T angle(T _cos_angle, T _sin_angle)
Definition: MathDefs.hh:140