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);
232 void GLPrimitive::addToRenderer_primitive(
class IRenderer* _renderer, RenderObject* _ro )
236 _ro->vertexBuffer = vbo_;
237 _ro->vertexDecl = &vertexDecl_;
240 _ro->glDrawArrays(GL_TRIANGLES, 0, numTris_ * 3);
242 _ro->glDrawArrays(GL_LINES, 0, numLines_ * 2);
244 _renderer->addRenderObject(_ro);
250 void GLPrimitive::updateVBOData() {
263 unsigned int GLPrimitive::getVBO()
265 return checkVBO() ? vbo_ : 0;
268 const VertexDeclaration* GLPrimitive::getVertexDecl()
const 279 GLSphere::GLSphere(
int _slices,
int _stacks) :
288 GLSphere::~GLSphere()
295 void GLSphere::draw(GLState& _state,
float _radius,
const ACG::Vec3f& _center)
297 _state.push_modelview_matrix();
300 _state.scale(_radius, _radius, _radius);
302 GLPrimitive::draw_primitive();
304 _state.pop_modelview_matrix();
309 void GLSphere::addToRenderer( IRenderer* _renderer,
const RenderObject* _base,
float _radius,
const ACG::Vec3f& _center )
311 RenderObject ro = *_base;
314 ro.modelview.scale((
double)_radius, (
double)_radius, (
double)_radius);
316 GLPrimitive::addToRenderer_primitive(_renderer, &ro);
322 int GLSphere::getNumTriangles()
324 return 2 * slices_ + (stacks_ - 2) * slices_ * 2;
329 void GLSphere::updateVBO()
331 for (
int sl = 0; sl < slices_; ++sl) {
335 addTriangle(0, st, sl + 1, st + 1, sl, st + 1);
338 for (
int st = 1; st < stacks_ - 1; ++st) {
339 addTriangle(sl, st, sl + 1, st, sl, st + 1);
340 addTriangle(sl + 1, st, sl + 1, st + 1, sl, st + 1);
344 addTriangle(0, stacks_, sl, stacks_ - 1, sl + 1, stacks_ - 1);
351 void GLSphere::addTriangle(
int sl0,
int st0,
int sl1,
int st1,
int sl2,
int st2)
357 n[0] = p[0] = positionOnSphere(sl0, st0);
358 n[1] = p[1] = positionOnSphere(sl1, st1);
359 n[2] = p[2] = positionOnSphere(sl2, st2);
363 tex[0] = texCoordOnSphere(sl0, st0);
364 tex[1] = texCoordOnSphere(sl1, st1);
365 tex[2] = texCoordOnSphere(sl2, st2);
367 addTriangleToVBO(p, n, tex);
372 ACG::Vec3f GLSphere::positionOnSphere(
int _sliceNumber,
int _stackNumber)
376 double alpha = (M_PI / double(stacks_)) *
double(_stackNumber);
377 double beta = ((2.0 * M_PI) /
double(slices_)) *
double(_sliceNumber);
379 double ringRadius = sin(alpha);
380 position[0] = sin(beta) * ringRadius;
381 position[1] = cos(beta) * ringRadius;
382 position[2] = cos(alpha);
389 ACG::Vec2f GLSphere::texCoordOnSphere(
int _sliceNumber,
int _stackNumber)
393 double alpha = (M_PI / double(stacks_)) *
double(_stackNumber);
394 texCoord[0] = double(_sliceNumber) / double(slices_);
395 texCoord[1] = 0.5 * (cos(alpha) + 1.0);
404 GLCone::GLCone(
int _slices,
int _stacks,
float _bottomRadius,
float _topRadius,
bool _bottomCap,
bool _topCap) :
407 bottomRadius_(_bottomRadius),
408 topRadius_(_topRadius),
409 bottomCap_(_bottomCap),
424 void GLCone::setBottomRadius(
float _bottomRadius) {
425 if (bottomRadius_ != _bottomRadius)
426 vboDataInvalid_ =
true;
427 bottomRadius_ = _bottomRadius;
432 void GLCone::setTopRadius(
float _topRadius) {
433 if (topRadius_ != _topRadius)
434 vboDataInvalid_ =
true;
435 topRadius_ = _topRadius;
440 void GLCone::setNormalOrientation(NormalOrientation orientation) {
441 if (normalOrientation_ != orientation)
442 vboDataInvalid_ =
true;
443 normalOrientation_ = orientation;
452 _state.push_modelview_matrix();
472 for (
int i = 0; i < 3; ++i) {
473 mAlign(i, 0) = vRotAxis[i];
474 mAlign(i, 1) = vUp[i];
475 mAlign(i, 2) = _upDir[i];
483 mAlign.
scale(1.0, 1.0, _height);
488 _state.mult_matrix(mAlign, mAlignInv);
490 GLPrimitive::draw_primitive();
492 _state.pop_modelview_matrix();
498 void GLCone::addToRenderer(IRenderer* _renderer,
499 const RenderObject* _base,
505 RenderObject ro = *_base;
525 for (
int i = 0; i < 3; ++i) {
526 mAlign(i, 0) = vRotAxis[i];
527 mAlign(i, 1) = vUp[i];
528 mAlign(i, 2) = _upDir[i];
536 mAlign.
scale(_radiusScale, _radiusScale, _height);
538 ro.modelview *= mAlign;
540 GLPrimitive::addToRenderer_primitive(_renderer, &ro);
545 int GLCone::getNumTriangles()
547 int numTris = stacks_ * slices_ * 2;
559 ACG::Vec3f GLCone::positionOnCone(
int _sliceNumber,
int _stackNumber)
563 double beta = ((2.0 * M_PI) / slices_) * _sliceNumber;
565 double relativeHeight = _stackNumber / (double) stacks_;
566 double ringRadius = (1.0 - relativeHeight) * bottomRadius_ + relativeHeight * topRadius_;
567 position[0] = sin(beta) * ringRadius;
568 position[1] = cos(beta) * ringRadius;
569 position[2] = relativeHeight;
576 ACG::Vec2f GLCone::texCoordOnCone(
int _sliceNumber,
int _stackNumber)
580 texCoord[0] = _sliceNumber / (double) slices_;
581 texCoord[1] = _stackNumber / (double) stacks_;
588 ACG::Vec3f GLCone::normalOnCone(
int _sliceNumber,
int _stackNumber)
592 double beta = ((2.0 * M_PI) / slices_) * _sliceNumber;
593 double relativeHeight = _stackNumber / (double) stacks_;
594 double ringRadius = (1.0 - relativeHeight) * bottomRadius_ + relativeHeight * topRadius_;
596 normal[0] = sin(beta) * ringRadius;
597 normal[1] = cos(beta) * ringRadius;
598 normal[2] = (bottomRadius_ - topRadius_);
606 void GLCone::addTriangle(
int sl0,
int st0,
int sl1,
int st1,
int sl2,
int st2)
612 p[0] = positionOnCone(sl0, st0);
613 p[1] = positionOnCone(sl1, st1);
614 p[2] = positionOnCone(sl2, st2);
615 if (normalOrientation_ == OUTSIDE) {
616 n[0] = normalOnCone(sl0, st0);
617 n[1] = normalOnCone(sl1, st1);
618 n[2] = normalOnCone(sl2, st2);
619 }
else if (normalOrientation_ == INSIDE) {
620 n[0] = -normalOnCone(sl0, st0);
621 n[1] = -normalOnCone(sl1, st1);
622 n[2] = -normalOnCone(sl2, st2);
624 tex[0] = texCoordOnCone(sl0, st0);
625 tex[1] = texCoordOnCone(sl1, st1);
626 tex[2] = texCoordOnCone(sl2, st2);
628 addTriangleToVBO(p, n, tex);
633 void GLCone::updateVBO()
635 for (
int sl = 0; sl < slices_; ++sl) {
643 p[1] = positionOnCone(sl + 1, stacks_);
644 p[2] = positionOnCone(sl, stacks_);
645 if (normalOrientation_ == OUTSIDE) {
649 }
else if (normalOrientation_ == INSIDE) {
656 double beta = ((2.0 * M_PI) / slices_) * (sl + 1);
658 beta = ((2.0 * M_PI) / slices_) * (sl);
661 addTriangleToVBO(p, n, tex);
664 for (
int st = 0; st < stacks_; ++st) {
665 addTriangle(sl, st, sl, st + 1, sl + 1, st);
666 addTriangle(sl + 1, st, sl, st + 1, sl + 1, st + 1);
675 p[1] = positionOnCone(sl, 0);
676 p[2] = positionOnCone(sl + 1, 0);
677 if (normalOrientation_ == OUTSIDE) {
681 }
else if (normalOrientation_ == INSIDE) {
688 double beta = ((2.0 * M_PI) / slices_) * (sl);
690 beta = ((2.0 * M_PI) / slices_) * (sl + 1);
693 addTriangleToVBO(p, n, tex);
702 GLCylinder::GLCylinder(
int _slices,
int _stacks,
float _radius,
bool _bottomCap,
bool _topCap) :
703 GLCone(_slices, _stacks, _radius, _radius, _bottomCap, _topCap)
722 innerRadius_(_innerRadius),
723 outerRadius_(_outerRadius),
724 startAngle_(_startAngle),
725 sweepAngle_(_sweepAngle)
732 void GLPartialDisk::setInnerRadius(
float _innerRadius) {
733 if (innerRadius_ != _innerRadius)
734 vboDataInvalid_ =
true;
735 innerRadius_ = _innerRadius;
740 void GLPartialDisk::setOuterRadius(
float _outerRadius) {
741 if (outerRadius_ != _outerRadius)
742 vboDataInvalid_ =
true;
743 outerRadius_ = _outerRadius;
748 int GLPartialDisk::getNumTriangles() {
749 return slices_ * (loops_+1) * 2;
754 void GLPartialDisk::updateVBO() {
755 assert(slices_ >= 2);
757 assert(outerRadius_ > 0.0f);
758 assert(innerRadius_ >= 0.0f);
759 assert(innerRadius_ < outerRadius_);
761 if (sweepAngle_ < -360.0f)
762 sweepAngle_ = 360.0f;
763 if (sweepAngle_ > 360.0f)
764 sweepAngle_ = 360.0f;
765 if (sweepAngle_ < 0) {
766 startAngle_ += sweepAngle_;
767 sweepAngle_ = -sweepAngle_;
770 float* sinCache =
new float[slices_+1];
771 float* cosCache =
new float[slices_+1];
774 float angleOffsetRadian = startAngle_ * M_PI / 180.0f;
775 float sweepAngleRadian = sweepAngle_ * M_PI / 180.0f;
776 for (
int i = 0; i < slices_+1; ++i) {
777 float angle = angleOffsetRadian + sweepAngleRadian * i/slices_;
778 sinCache[i] = sin(angle);
779 cosCache[i] = cos(angle);
783 float deltaRadius = outerRadius_ - innerRadius_;
784 for (
int i = loops_+1; i > 0; --i) {
787 for (
int j = 0; j < slices_; ++j) {
797 float innerRadius = outerRadius_ - deltaRadius * ((float) i / (loops_ + 1));
799 float outerRadius = outerRadius_ - deltaRadius * ((float) (i - 1) / (loops_ + 1));
806 p[0] =
ACG::Vec3f(innerRadius * sinCache[j], innerRadius * cosCache[j], 0.0f);
807 p[1] =
ACG::Vec3f(outerRadius * sinCache[j], outerRadius * cosCache[j], 0.0f);
808 p[2] =
ACG::Vec3f(outerRadius * sinCache[j+1], outerRadius * cosCache[j+1], 0.0f);
818 addTriangleToVBO(p, n, tex);
825 p2[0] =
ACG::Vec3f(innerRadius * sinCache[j], innerRadius * cosCache[j], 0.0f);
826 p2[1] =
ACG::Vec3f(outerRadius * sinCache[j+1], outerRadius * cosCache[j+1], 0.0f);
827 p2[2] =
ACG::Vec3f(innerRadius * sinCache[j+1], innerRadius * cosCache[j+1], 0.0f);
837 addTriangleToVBO(p2, n2, tex2);
869 for (
int i = 0; i < 3; ++i) {
870 mAlign(i, 0) = vRotAxis[i];
871 mAlign(i, 1) = vUp[i];
872 mAlign(i, 2) = _upDir[i];
884 GLPrimitive::draw_primitive();
899 GLDisk::GLDisk(
int _slices,
int _loops,
float _innerRadius,
float _outerRadius) :
900 GLPartialDisk(_slices, _loops, _innerRadius, _outerRadius, 0.0f, 360.0f)
918 int GLBox::getNumTriangles()
925 void GLBox::updateVBO()
927 static const Vec3f pos[8] =
929 Vec3f(-0.5f,-0.5f,0.5f),
Vec3f(-0.5f,-0.5f,-0.5f),
Vec3f(0.5f,-0.5f,-0.5f),
931 Vec3f(0.5f,0.5f,-0.5f),
Vec3f(-0.5f,0.5f,-0.5f)
934 static const Vec3f norm[6] =
940 static const Vec2f texc[4] =
946 static const int tris[12][9] =
948 {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},
949 {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},
950 {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},
951 {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}
954 for (
int i = 0; i < 12; ++i)
956 Vec3f triPos[3] = { pos[tris[i][0]], pos[tris[i][1]], pos[tris[i][2]] };
957 Vec3f triNorm[3] = { norm[tris[i][3]], norm[tris[i][4]], norm[tris[i][5]] };
958 Vec2f triTexc[3] = { texc[tris[i][6]], texc[tris[i][7]], texc[tris[i][8]] };
960 addTriangleToVBO(triPos, triNorm, triTexc);
966 GLLineBox::GLLineBox()
971 GLLineBox::~GLLineBox()
977 int GLLineBox::getNumTriangles()
982 int GLLineBox::getNumLines()
989 void GLLineBox::updateVBO()
991 static const Vec3f pos[8] =
993 Vec3f(-0.5f,-0.5f,0.5f),
Vec3f(-0.5f,-0.5f,-0.5f),
Vec3f(0.5f,-0.5f,-0.5f),
995 Vec3f(0.5f,0.5f,-0.5f),
Vec3f(-0.5f,0.5f,-0.5f)
998 static const Vec3f norm[6] =
1004 static const Vec2f texc[4] =
1010 static const int lines[12][6] =
1012 {1,2, 0,0, 0,3}, {0,3, 0,0, 0,3}, {4,5, 0,0, 0,3}, {7,6, 0,0, 0,3},
1013 {1,7, 0,0, 0,3}, {0,4, 0,0, 0,3}, {2,6, 0,0, 0,3}, {3,5, 0,0, 0,3},
1014 {1,0, 0,0, 0,3}, {2,3, 0,0, 0,3}, {7,4, 0,0, 0,3}, {6,5, 0,0, 0,3}
1017 for (
int i = 0; i < 12; ++i)
1019 Vec3f p[2] = { pos[lines[i][0]], pos[lines[i][1]]};
1020 Vec3f n[2] = { norm[lines[i][2]], norm[lines[i][3]]};
1021 Vec2f t[2] = { texc[lines[i][4]], texc[lines[i][5]]};
1023 addLineToVBO(p, n, t);
VectorT< float, 2 > Vec2f
void push_modelview_matrix()
push modelview matrix
void identity()
setup an identity matrix
VectorT< float, 3 > Vec3f
void translate(double _x, double _y, double _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
translate by (_x, _y, _z)
void mult_matrix(const GLMatrixd &_m, const GLMatrixd &_inv_m, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
multiply by a given transformation matrix
Namespace providing different geometric functions concerning angles.
GLPartialDisk(int _slices, int _loops, float _innerRadius, float _outerRadius, float _startAngle, float _sweepAngle)
void scale(Scalar _x, Scalar _y, Scalar _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
multiply self with scaling matrix (x,y,z)
GLDisk(int _slices, int _loops, float _innerRadius, float _outerRadius)
void pop_modelview_matrix()
pop modelview matrix
auto normalize() -> decltype(*this/=std::declval< VectorT< S, DIM >>().norm())
bool invert()
matrix inversion (returns true on success)
osg::Vec3f::ValueType dot(const osg::Vec3f &_v1, const osg::Vec3f &_v2)
Adapter for osg vector member computing a scalar product.
osg::Vec3f cross(const osg::Vec3f &_v1, const osg::Vec3f &_v2)
Adapter for osg vector member computing a scalar product.