50 #include <ACG/GL/acg_glew.hh>
52 #include "GLPrimitives.hh"
53 #include <ACG/GL/IRenderer.hh>
62 GLPrimitive::GLPrimitive() :
63 vboDataInvalid_(true),
64 normalOrientation_(OUTSIDE),
79 GLPrimitive::~GLPrimitive()
82 glDeleteBuffers(1, &vbo_);
91 if (!numTris_ || vboDataInvalid_)
92 numTris_ = getNumTriangles();
97 assert(numLines_ == 0);
101 vboData_ =
new float[8 * 3 * numTris_];
103 if (curTriPtr_ == numTris_)
106 float* pTri = &vboData_[0] + (curTriPtr_++) * 3 * 8;
109 for (
int i = 0; i < 3; ++i) {
110 for (
int k = 0; k < 3; ++k)
111 *(pTri++) = _p[i][k];
113 for (
int k = 0; k < 3; ++k)
114 *(pTri++) = _n[i][k];
116 for (
int k = 0; k < 2; ++k)
117 *(pTri++) = _tex[i][k];
124 if (!numLines_ || vboDataInvalid_)
125 numLines_ = getNumLines();
130 assert(numTris_ == 0);
133 vboData_ =
new float[8 * 2 * numLines_];
135 if (curTriPtr_ == numLines_)
138 float* pLine = &vboData_[0] + (curTriPtr_++) * 2 * 8;
141 for (
int i = 0; i < 2; ++i) {
142 for (
int k = 0; k < 3; ++k)
143 *(pLine++) = _p[i][k];
145 for (
int k = 0; k < 3; ++k)
146 *(pLine++) = _n[i][k];
148 for (
int k = 0; k < 2; ++k)
149 *(pLine++) = _tex[i][k];
156 void GLPrimitive::bindVBO()
160 glBindBuffer(GL_ARRAY_BUFFER, vbo_);
162 glVertexPointer(3, GL_FLOAT, 32, 0);
163 glEnableClientState(GL_VERTEX_ARRAY);
165 glNormalPointer(GL_FLOAT, 32, (GLvoid*) 12);
166 glEnableClientState(GL_NORMAL_ARRAY);
168 glClientActiveTexture(GL_TEXTURE0);
169 glTexCoordPointer(2, GL_FLOAT, 32, (GLvoid*) 24);
170 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
177 bool GLPrimitive::checkVBO()
183 const int bufSize = numTris_ ? numTris_ * 3 * 8 * 4 : numLines_ * 2 * 8 * 4;
186 if (!vboData_ || (!numTris_ && !numLines_) || (numTris_ && numLines_))
190 glGenBuffers(1, &vbo_);
191 glBindBuffer(GL_ARRAY_BUFFER, vbo_);
192 glBufferData(GL_ARRAY_BUFFER, bufSize, vboData_, GL_STATIC_DRAW);
196 }
else if (vboDataInvalid_) {
198 glBindBuffer(GL_ARRAY_BUFFER, vbo_);
199 glBufferData(GL_ARRAY_BUFFER, bufSize, vboData_, GL_STATIC_DRAW);
200 vboDataInvalid_ =
false;
208 void GLPrimitive::unBindVBO()
210 glBindBuffer(GL_ARRAY_BUFFER, 0);
211 glDisableClientState(GL_VERTEX_ARRAY);
212 glDisableClientState(GL_NORMAL_ARRAY);
213 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
218 void GLPrimitive::draw_primitive()
223 glDrawArrays(GL_TRIANGLES, 0, numTris_ * 3);
225 glDrawArrays(GL_LINES, 0, numLines_ * 2);
236 glBindBuffer(GL_ARRAY_BUFFER, vbo_);
240 glDrawArrays(GL_TRIANGLES, 0, numTris_ * 3);
242 glDrawArrays(GL_LINES, 0, numLines_ * 2);
245 glBindBuffer(GL_ARRAY_BUFFER, 0);
251 void GLPrimitive::addToRenderer_primitive(
class IRenderer* _renderer, RenderObject* _ro )
255 _ro->vertexBuffer = vbo_;
256 _ro->vertexDecl = &vertexDecl_;
259 _ro->glDrawArrays(GL_TRIANGLES, 0, numTris_ * 3);
261 _ro->glDrawArrays(GL_LINES, 0, numLines_ * 2);
263 _renderer->addRenderObject(_ro);
269 void GLPrimitive::updateVBOData() {
282 unsigned int GLPrimitive::getVBO()
284 return checkVBO() ? vbo_ : 0;
287 const VertexDeclaration* GLPrimitive::getVertexDecl()
const
298 GLSphere::GLSphere(
int _slices,
int _stacks) :
307 GLSphere::~GLSphere()
314 void GLSphere::draw(GLState& _state,
float _radius,
const ACG::Vec3f& _center)
316 _state.push_modelview_matrix();
319 _state.scale(_radius, _radius, _radius);
321 GLPrimitive::draw_primitive();
323 _state.pop_modelview_matrix();
328 void GLSphere::addToRenderer( IRenderer* _renderer,
const RenderObject* _base,
float _radius,
const ACG::Vec3f& _center )
330 RenderObject ro = *_base;
333 ro.modelview.scale((
double)_radius, (
double)_radius, (
double)_radius);
335 GLPrimitive::addToRenderer_primitive(_renderer, &ro);
341 int GLSphere::getNumTriangles()
343 return 2 * slices_ + (stacks_ - 2) * slices_ * 2;
348 void GLSphere::updateVBO()
350 for (
int sl = 0; sl < slices_; ++sl) {
354 addTriangle(0, st, sl + 1, st + 1, sl, st + 1);
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);
363 addTriangle(0, stacks_, sl, stacks_ - 1, sl + 1, stacks_ - 1);
370 void GLSphere::addTriangle(
int sl0,
int st0,
int sl1,
int st1,
int sl2,
int st2)
376 n[0] = p[0] = positionOnSphere(sl0, st0);
377 n[1] = p[1] = positionOnSphere(sl1, st1);
378 n[2] = p[2] = positionOnSphere(sl2, st2);
382 tex[0] = texCoordOnSphere(sl0, st0);
383 tex[1] = texCoordOnSphere(sl1, st1);
384 tex[2] = texCoordOnSphere(sl2, st2);
386 addTriangleToVBO(p, n, tex);
391 ACG::Vec3f GLSphere::positionOnSphere(
int _sliceNumber,
int _stackNumber)
395 double alpha = (M_PI / double(stacks_)) *
double(_stackNumber);
396 double beta = ((2.0 * M_PI) /
double(slices_)) *
double(_sliceNumber);
398 double ringRadius = sin(alpha);
399 position[0] = sin(beta) * ringRadius;
400 position[1] = cos(beta) * ringRadius;
401 position[2] = cos(alpha);
408 ACG::Vec2f GLSphere::texCoordOnSphere(
int _sliceNumber,
int _stackNumber)
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);
423 GLCone::GLCone(
int _slices,
int _stacks,
float _bottomRadius,
float _topRadius,
bool _bottomCap,
bool _topCap) :
426 bottomRadius_(_bottomRadius),
427 topRadius_(_topRadius),
428 bottomCap_(_bottomCap),
443 void GLCone::setBottomRadius(
float _bottomRadius) {
444 if (bottomRadius_ != _bottomRadius)
445 vboDataInvalid_ =
true;
446 bottomRadius_ = _bottomRadius;
451 void GLCone::setTopRadius(
float _topRadius) {
452 if (topRadius_ != _topRadius)
453 vboDataInvalid_ =
true;
454 topRadius_ = _topRadius;
459 void GLCone::setNormalOrientation(NormalOrientation orientation) {
460 if (normalOrientation_ != orientation)
461 vboDataInvalid_ =
true;
462 normalOrientation_ = orientation;
471 _state.push_modelview_matrix();
486 vRotAxis.normalize();
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];
502 mAlign.
scale(1.0, 1.0, _height);
507 _state.mult_matrix(mAlign, mAlignInv);
509 GLPrimitive::draw_primitive();
511 _state.pop_modelview_matrix();
517 void GLCone::addToRenderer(IRenderer* _renderer,
518 const RenderObject* _base,
524 RenderObject ro = *_base;
539 vRotAxis.normalize();
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];
555 mAlign.
scale(_radiusScale, _radiusScale, _height);
557 ro.modelview *= mAlign;
559 GLPrimitive::addToRenderer_primitive(_renderer, &ro);
564 int GLCone::getNumTriangles()
566 int numTris = stacks_ * slices_ * 2;
578 ACG::Vec3f GLCone::positionOnCone(
int _sliceNumber,
int _stackNumber)
582 double beta = ((2.0 * M_PI) / slices_) * _sliceNumber;
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;
595 ACG::Vec2f GLCone::texCoordOnCone(
int _sliceNumber,
int _stackNumber)
599 texCoord[0] = _sliceNumber / (double) slices_;
600 texCoord[1] = _stackNumber / (double) stacks_;
607 ACG::Vec3f GLCone::normalOnCone(
int _sliceNumber,
int _stackNumber)
611 double beta = ((2.0 * M_PI) / slices_) * _sliceNumber;
612 double relativeHeight = _stackNumber / (double) stacks_;
613 double ringRadius = (1.0 - relativeHeight) * bottomRadius_ + relativeHeight * topRadius_;
615 normal[0] = sin(beta) * ringRadius;
616 normal[1] = cos(beta) * ringRadius;
617 normal[2] = (bottomRadius_ - topRadius_);
625 void GLCone::addTriangle(
int sl0,
int st0,
int sl1,
int st1,
int sl2,
int st2)
631 p[0] = positionOnCone(sl0, st0);
632 p[1] = positionOnCone(sl1, st1);
633 p[2] = positionOnCone(sl2, st2);
634 if (normalOrientation_ == OUTSIDE) {
635 n[0] = normalOnCone(sl0, st0);
636 n[1] = normalOnCone(sl1, st1);
637 n[2] = normalOnCone(sl2, st2);
638 }
else if (normalOrientation_ == INSIDE) {
639 n[0] = -normalOnCone(sl0, st0);
640 n[1] = -normalOnCone(sl1, st1);
641 n[2] = -normalOnCone(sl2, st2);
643 tex[0] = texCoordOnCone(sl0, st0);
644 tex[1] = texCoordOnCone(sl1, st1);
645 tex[2] = texCoordOnCone(sl2, st2);
647 addTriangleToVBO(p, n, tex);
652 void GLCone::updateVBO()
654 for (
int sl = 0; sl < slices_; ++sl) {
662 p[1] = positionOnCone(sl + 1, stacks_);
663 p[2] = positionOnCone(sl, stacks_);
664 if (normalOrientation_ == OUTSIDE) {
668 }
else if (normalOrientation_ == INSIDE) {
675 double beta = ((2.0 * M_PI) / slices_) * (sl + 1);
677 beta = ((2.0 * M_PI) / slices_) * (sl);
680 addTriangleToVBO(p, n, tex);
683 for (
int st = 0; st < stacks_; ++st) {
684 addTriangle(sl, st, sl, st + 1, sl + 1, st);
685 addTriangle(sl + 1, st, sl, st + 1, sl + 1, st + 1);
694 p[1] = positionOnCone(sl, 0);
695 p[2] = positionOnCone(sl + 1, 0);
696 if (normalOrientation_ == OUTSIDE) {
700 }
else if (normalOrientation_ == INSIDE) {
707 double beta = ((2.0 * M_PI) / slices_) * (sl);
709 beta = ((2.0 * M_PI) / slices_) * (sl + 1);
712 addTriangleToVBO(p, n, tex);
721 GLCylinder::GLCylinder(
int _slices,
int _stacks,
float _radius,
bool _bottomCap,
bool _topCap) :
722 GLCone(_slices, _stacks, _radius, _radius, _bottomCap, _topCap)
741 innerRadius_(_innerRadius),
742 outerRadius_(_outerRadius),
743 startAngle_(_startAngle),
744 sweepAngle_(_sweepAngle)
751 void GLPartialDisk::setInnerRadius(
float _innerRadius) {
752 if (innerRadius_ != _innerRadius)
753 vboDataInvalid_ =
true;
754 innerRadius_ = _innerRadius;
759 void GLPartialDisk::setOuterRadius(
float _outerRadius) {
760 if (outerRadius_ != _outerRadius)
761 vboDataInvalid_ =
true;
762 outerRadius_ = _outerRadius;
767 int GLPartialDisk::getNumTriangles() {
768 return slices_ * (loops_+1) * 2;
773 void GLPartialDisk::updateVBO() {
774 assert(slices_ >= 2);
776 assert(outerRadius_ > 0.0f);
777 assert(innerRadius_ >= 0.0f);
778 assert(innerRadius_ < outerRadius_);
780 if (sweepAngle_ < -360.0f)
781 sweepAngle_ = 360.0f;
782 if (sweepAngle_ > 360.0f)
783 sweepAngle_ = 360.0f;
784 if (sweepAngle_ < 0) {
785 startAngle_ += sweepAngle_;
786 sweepAngle_ = -sweepAngle_;
789 float* sinCache =
new float[slices_+1];
790 float* cosCache =
new float[slices_+1];
793 float angleOffsetRadian = startAngle_ * M_PI / 180.0f;
794 float sweepAngleRadian = sweepAngle_ * M_PI / 180.0f;
795 for (
int i = 0; i < slices_+1; ++i) {
796 float angle = angleOffsetRadian + sweepAngleRadian * i/slices_;
797 sinCache[i] = sin(angle);
798 cosCache[i] = cos(angle);
802 float deltaRadius = outerRadius_ - innerRadius_;
803 for (
int i = loops_+1; i > 0; --i) {
806 for (
int j = 0; j < slices_; ++j) {
816 float innerRadius = outerRadius_ - deltaRadius * ((float) i / (loops_ + 1));
818 float outerRadius = outerRadius_ - deltaRadius * ((float) (i - 1) / (loops_ + 1));
825 p[0] =
ACG::Vec3f(innerRadius * sinCache[j], innerRadius * cosCache[j], 0.0f);
826 p[1] =
ACG::Vec3f(outerRadius * sinCache[j], outerRadius * cosCache[j], 0.0f);
827 p[2] =
ACG::Vec3f(outerRadius * sinCache[j+1], outerRadius * cosCache[j+1], 0.0f);
837 addTriangleToVBO(p, n, tex);
844 p2[0] =
ACG::Vec3f(innerRadius * sinCache[j], innerRadius * cosCache[j], 0.0f);
845 p2[1] =
ACG::Vec3f(outerRadius * sinCache[j+1], outerRadius * cosCache[j+1], 0.0f);
846 p2[2] =
ACG::Vec3f(innerRadius * sinCache[j+1], innerRadius * cosCache[j+1], 0.0f);
856 addTriangleToVBO(p2, n2, tex2);
868 _state.push_modelview_matrix();
883 vRotAxis.normalize();
888 for (
int i = 0; i < 3; ++i) {
889 mAlign(i, 0) = vRotAxis[i];
890 mAlign(i, 1) = vUp[i];
891 mAlign(i, 2) = _upDir[i];
901 _state.mult_matrix(mAlign, mAlignInv);
903 GLPrimitive::draw_primitive();
905 _state.pop_modelview_matrix();
918 GLDisk::GLDisk(
int _slices,
int _loops,
float _innerRadius,
float _outerRadius) :
919 GLPartialDisk(_slices, _loops, _innerRadius, _outerRadius, 0.0f, 360.0f)
937 int GLBox::getNumTriangles()
944 void GLBox::updateVBO()
946 static const Vec3f pos[8] =
948 Vec3f(-0.5f,-0.5f,0.5f),
Vec3f(-0.5f,-0.5f,-0.5f),
Vec3f(0.5f,-0.5f,-0.5f),
950 Vec3f(0.5f,0.5f,-0.5f),
Vec3f(-0.5f,0.5f,-0.5f)
953 static const Vec3f norm[6] =
959 static const Vec2f texc[4] =
965 static const int tris[12][9] =
967 {0,1,2 ,0,0,0 ,0,1,2}, {2,3,0 ,0,0,0 ,2,3,0}, {4,5,6 ,1,1,1 ,3,0,1},
968 {6,7,4 ,1,1,1 ,1,2,3}, {0,3,5 ,2,2,2 ,3,0,1}, {5,4,0 ,2,2,2 ,1,2,3},
969 {3,2,6 ,3,3,3 ,3,0,1}, {6,5,3 ,3,3,3 ,1,2,3}, {2,1,7 ,4,4,4 ,3,0,1},
970 {7,6,2 ,4,4,4 ,1,2,3}, {1,0,4 ,5,5,5 ,3,0,1}, {4,7,1 ,5,5,5 ,1,2,3}
973 for (
int i = 0; i < 12; ++i)
975 Vec3f triPos[3] = { pos[tris[i][0]], pos[tris[i][1]], pos[tris[i][2]] };
976 Vec3f triNorm[3] = { norm[tris[i][3]], norm[tris[i][4]], norm[tris[i][5]] };
977 Vec2f triTexc[3] = { texc[tris[i][6]], texc[tris[i][7]], texc[tris[i][8]] };
979 addTriangleToVBO(triPos, triNorm, triTexc);
985 GLLineBox::GLLineBox()
990 GLLineBox::~GLLineBox()
996 int GLLineBox::getNumTriangles()
1001 int GLLineBox::getNumLines()
1008 void GLLineBox::updateVBO()
1010 static const Vec3f pos[8] =
1012 Vec3f(-0.5f,-0.5f,0.5f),
Vec3f(-0.5f,-0.5f,-0.5f),
Vec3f(0.5f,-0.5f,-0.5f),
1013 Vec3f(0.5f,-0.5f,0.5f),
Vec3f(-0.5f,0.5f,0.5f),
Vec3f(0.5f,0.5f,0.5f),
1014 Vec3f(0.5f,0.5f,-0.5f),
Vec3f(-0.5f,0.5f,-0.5f)
1017 static const Vec3f norm[6] =
1023 static const Vec2f texc[4] =
1029 static const int lines[12][6] =
1031 {1,2, 0,0, 0,3}, {0,3, 0,0, 0,3}, {4,5, 0,0, 0,3}, {7,6, 0,0, 0,3},
1032 {1,7, 0,0, 0,3}, {0,4, 0,0, 0,3}, {2,6, 0,0, 0,3}, {3,5, 0,0, 0,3},
1033 {1,0, 0,0, 0,3}, {2,3, 0,0, 0,3}, {7,4, 0,0, 0,3}, {6,5, 0,0, 0,3}
1036 for (
int i = 0; i < 12; ++i)
1038 Vec3f p[2] = { pos[lines[i][0]], pos[lines[i][1]]};
1039 Vec3f n[2] = { norm[lines[i][2]], norm[lines[i][3]]};
1040 Vec2f t[2] = { texc[lines[i][4]], texc[lines[i][5]]};
1042 addLineToVBO(p, n, t);
T angle(T _cos_angle, T _sin_angle)
GLPartialDisk(int _slices, int _loops, float _innerRadius, float _outerRadius, float _startAngle, float _sweepAngle)
osg::Vec3f::ValueType dot(const osg::Vec3f &_v1, const osg::Vec3f &_v2)
Adapter for osg vector member computing a scalar product.
Namespace providing different geometric functions concerning angles.
GLDisk(int _slices, int _loops, float _innerRadius, float _outerRadius)
VectorT< float, 3 > Vec3f
VectorT< float, 2 > Vec2f
void activateShaderPipeline(GLSL::Program *_prog) const
void deactivateShaderPipeline(GLSL::Program *_prog) const
void scale(Scalar _x, Scalar _y, Scalar _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
multiply self with scaling matrix (x,y,z)
osg::Vec3f cross(const osg::Vec3f &_v1, const osg::Vec3f &_v2)
Adapter for osg vector member computing a scalar product.
void identity()
setup an identity matrix