From e5ab4355beb22eab973e4e3b884bb5578c0bee44 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Tue, 23 Aug 2016 11:08:25 +0100 Subject: [PATCH] Added osg::convertShapeToGeometry(...) convinience functions for creating osg::Geometry from osg::Shape descriptions. --- include/osg/Shape | 44 ++++++++++++---------- src/osg/Shape.cpp | 95 ++++++++++++++++++++++++++++++++--------------- 2 files changed, 90 insertions(+), 49 deletions(-) diff --git a/include/osg/Shape b/include/osg/Shape index 09ea6e8c8..7582714d4 100644 --- a/include/osg/Shape +++ b/include/osg/Shape @@ -33,13 +33,13 @@ class ConstShapeVisitor; * the standard pure virtual methods which are required for all Object * subclasses.*/ #define META_Shape(library,name) \ - virtual osg::Object* cloneType() const { return new name(); } \ - virtual osg::Object* clone(const osg::CopyOp& copyop) const { return new name (*this,copyop); } \ - virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast(obj)!=NULL; } \ + virtual Object* cloneType() const { return new name(); } \ + virtual Object* clone(const CopyOp& copyop) const { return new name (*this,copyop); } \ + virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast(obj)!=NULL; } \ virtual const char* libraryName() const { return #library; } \ virtual const char* className() const { return #name; } \ - virtual void accept(osg::ShapeVisitor& sv) { sv.apply(*this); } \ - virtual void accept(osg::ConstShapeVisitor& csv) const { csv.apply(*this); } + virtual void accept(ShapeVisitor& sv) { sv.apply(*this); } \ + virtual void accept(ConstShapeVisitor& csv) const { csv.apply(*this); } /** Base class for all shape types. * Shapes are used to either for culling and collision detection or @@ -151,7 +151,7 @@ class OSG_EXPORT Sphere : public Shape _center(0.0f,0.0f,0.0f), _radius(1.0f) {} - Sphere(const osg::Vec3& center,float radius): + Sphere(const Vec3& center,float radius): _center(center), _radius(radius) {} @@ -193,11 +193,11 @@ class OSG_EXPORT Box : public Shape _center(0.0f,0.0f,0.0f), _halfLengths(0.5f,0.5f,0.5f) {} - Box(const osg::Vec3& center,float width): + Box(const Vec3& center,float width): _center(center), _halfLengths(width*0.5f,width*0.5f,width*0.5f) {} - Box(const osg::Vec3& center,float lengthX,float lengthY, float lengthZ): + Box(const Vec3& center,float lengthX,float lengthY, float lengthZ): _center(center), _halfLengths(lengthX*0.5f,lengthY*0.5f,lengthZ*0.5f) {} @@ -249,7 +249,7 @@ class OSG_EXPORT Cone : public Shape _radius(1.0f), _height(1.0f) {} - Cone(const osg::Vec3& center,float radius,float height): + Cone(const Vec3& center,float radius,float height): _center(center), _radius(radius), _height(height) {} @@ -309,7 +309,7 @@ class OSG_EXPORT Cylinder : public Shape _radius(1.0f), _height(1.0f) {} - Cylinder(const osg::Vec3& center,float radius,float height): + Cylinder(const Vec3& center,float radius,float height): _center(center), _radius(radius), _height(height) {} @@ -365,7 +365,7 @@ class OSG_EXPORT Capsule : public Shape _radius(1.0f), _height(1.0f) {} - Capsule(const osg::Vec3& center,float radius,float height): + Capsule(const Vec3& center,float radius,float height): _center(center), _radius(radius), _height(height) {} @@ -496,8 +496,8 @@ class OSG_EXPORT HeightField : public Shape inline unsigned int getNumColumns() const { return _columns; } inline unsigned int getNumRows() const { return _rows; } - inline void setOrigin(const osg::Vec3& origin) { _origin = origin; } - inline const osg::Vec3& getOrigin() const { return _origin; } + inline void setOrigin(const Vec3& origin) { _origin = origin; } + inline const Vec3& getOrigin() const { return _origin; } inline void setXInterval(float dx) { _dx = dx; } inline float getXInterval() const { return _dx; } @@ -506,10 +506,10 @@ class OSG_EXPORT HeightField : public Shape inline float getYInterval() const { return _dy; } /** Get the FloatArray height data.*/ - osg::FloatArray* getFloatArray() { return _heights.get(); } + FloatArray* getFloatArray() { return _heights.get(); } /** Get the const FloatArray height data.*/ - const osg::FloatArray* getFloatArray() const { return _heights.get(); } + const FloatArray* getFloatArray() const { return _heights.get(); } HeightList& getHeightList() { return _heights->asVector(); } @@ -571,7 +571,7 @@ class OSG_EXPORT HeightField : public Shape unsigned int _columns,_rows; - osg::Vec3 _origin; // _origin is the min value of the X and Y coordinates. + Vec3 _origin; // _origin is the min value of the X and Y coordinates. float _dx; float _dy; @@ -579,7 +579,7 @@ class OSG_EXPORT HeightField : public Shape unsigned int _borderWidth; Quat _rotation; - osg::ref_ptr _heights; + ref_ptr _heights; }; @@ -747,12 +747,12 @@ class TessellationHints : public Object // forward declare; class Geometry; -/** Convinience class for populating an osg::Geomtry with vertex, normals, texture coords and primitives that can render a Shape. */ +/** Convinience class for populating an Geomtry with vertex, normals, texture coords and primitives that can render a Shape. */ class OSG_EXPORT BuildShapeGeometryVisitor : public ConstShapeVisitor { public: - BuildShapeGeometryVisitor(Geometry* geometry, TessellationHints* hints); + BuildShapeGeometryVisitor(Geometry* geometry, const TessellationHints* hints); virtual void apply(const Sphere&); virtual void apply(const Box&); @@ -773,7 +773,7 @@ class OSG_EXPORT BuildShapeGeometryVisitor : public ConstShapeVisitor void Vertex(const Vec3f& v) { _vertices->push_back(v); } void Vertex3f(float x, float y, float z) { _vertices->push_back(Vec3(x,y,z)); } - void setMatrix(const osg::Matrixd& m); + void setMatrix(const Matrixd& m); void Begin(GLenum mode); void End(); @@ -801,6 +801,10 @@ protected: Matrixd _inverse; }; +extern OSG_EXPORT Geometry* convertShapeToGeometry(const Shape& shape, const TessellationHints* hints); + +extern OSG_EXPORT Geometry* convertShapeToGeometry(const Shape& shape, const TessellationHints* hints, const Vec4& color, Array::Binding colorBinding=Array::BIND_OVERALL); + } #endif diff --git a/src/osg/Shape.cpp b/src/osg/Shape.cpp index 6b7b9bb51..aa2e4038d 100644 --- a/src/osg/Shape.cpp +++ b/src/osg/Shape.cpp @@ -70,7 +70,7 @@ HeightField::HeightField(): _skirtHeight(0.0f), _borderWidth(0) { - _heights = new osg::FloatArray; + _heights = new FloatArray; } HeightField::HeightField(const HeightField& mesh,const CopyOp& copyop): @@ -82,7 +82,7 @@ HeightField::HeightField(const HeightField& mesh,const CopyOp& copyop): _dy(mesh._dy), _skirtHeight(mesh._skirtHeight), _borderWidth(mesh._borderWidth), - _heights(new osg::FloatArray(*mesh._heights)) + _heights(new FloatArray(*mesh._heights)) { } @@ -184,13 +184,13 @@ CompositeShape::~CompositeShape() const unsigned int MIN_NUM_ROWS = 3; const unsigned int MIN_NUM_SEGMENTS = 5; -BuildShapeGeometryVisitor::BuildShapeGeometryVisitor(Geometry* geometry, TessellationHints* hints): +BuildShapeGeometryVisitor::BuildShapeGeometryVisitor(Geometry* geometry, const TessellationHints* hints): _geometry(geometry), _hints(hints) { - _vertices = dynamic_cast(geometry->getVertexArray()); - _normals = dynamic_cast(geometry->getNormalArray()); - _texcoords = dynamic_cast(geometry->getTexCoordArray(0)); + _vertices = dynamic_cast(geometry->getVertexArray()); + _normals = dynamic_cast(geometry->getNormalArray()); + _texcoords = dynamic_cast(geometry->getTexCoordArray(0)); bool requiresClearOfPrimitiveSets = false; @@ -225,7 +225,7 @@ BuildShapeGeometryVisitor::BuildShapeGeometryVisitor(Geometry* geometry, Tessell _start_index = 0; } -void BuildShapeGeometryVisitor::setMatrix(const osg::Matrixd& m) +void BuildShapeGeometryVisitor::setMatrix(const Matrixd& m) { _matrix = m; @@ -247,10 +247,10 @@ void BuildShapeGeometryVisitor::End() for(unsigned int i=_start_index; i<_vertices->size(); ++i) { - osg::Vec3& v = (*_vertices)[i]; + Vec3& v = (*_vertices)[i]; v = v * _matrix; - osg::Vec3& n = (*_normals)[i]; + Vec3& n = (*_normals)[i]; n = _inverse * n; n.normalize(); } @@ -265,7 +265,7 @@ void BuildShapeGeometryVisitor::End() void BuildShapeGeometryVisitor::drawCylinderBody(unsigned int numSegments, float radius, float height) { - const float angleDelta = 2.0f*osg::PIf/(float)numSegments; + const float angleDelta = 2.0f*PIf/(float)numSegments; const float texCoordDelta = 1.0f/(float)numSegments; const float r = radius; @@ -295,7 +295,7 @@ void BuildShapeGeometryVisitor::drawCylinderBody(unsigned int numSegments, float { float c = cosf(angle); float s = sinf(angle); - osg::Vec3 n(c,s,0.0f); + Vec3 n(c,s,0.0f); Normal(n); TexCoord2f(texCoord,1.0f); @@ -307,7 +307,7 @@ void BuildShapeGeometryVisitor::drawCylinderBody(unsigned int numSegments, float } // do last point by hand to ensure no round off errors. - osg::Vec3 n(1.0f,0.0f,0.0f); + Vec3 n(1.0f,0.0f,0.0f); Normal(n); TexCoord2f(1.0f,1.0f); @@ -326,7 +326,7 @@ void BuildShapeGeometryVisitor::drawCylinderBody(unsigned int numSegments, float { float c = cosf(angle); float s = sinf(angle); - osg::Vec3 n(-c,-s,0.0f); + Vec3 n(-c,-s,0.0f); Normal(n); TexCoord2f(texCoord,0.0f); @@ -338,7 +338,7 @@ void BuildShapeGeometryVisitor::drawCylinderBody(unsigned int numSegments, float } // do last point by hand to ensure no round off errors. - osg::Vec3 n(-1.0f,0.0f,0.0f); + Vec3 n(-1.0f,0.0f,0.0f); Normal(n); TexCoord2f(1.0f,0.0f); @@ -355,7 +355,7 @@ void BuildShapeGeometryVisitor::drawCylinderBody(unsigned int numSegments, float void BuildShapeGeometryVisitor::drawHalfSphere(unsigned int numSegments, unsigned int numRows, float radius, SphereHalf which, float zOffset) { - float lDelta = osg::PIf/(float)numRows; + float lDelta = PIf/(float)numRows; float vDelta = 1.0f/(float)numRows; bool top = (which==SphereTopHalf); @@ -363,10 +363,10 @@ void BuildShapeGeometryVisitor::drawHalfSphere(unsigned int numSegments, unsigne bool drawFrontFace = _hints ? _hints->getCreateFrontFace() : true; bool drawBackFace = _hints ? _hints->getCreateBackFace() : false; - float angleDelta = osg::PIf*2.0f/(float)numSegments; + float angleDelta = PIf*2.0f/(float)numSegments; float texCoordHorzDelta = 1.0f/(float)numSegments; - float lBase=-osg::PIf*0.5f + (top?(lDelta*(numRows/2)):0.0f); + float lBase=-PIf*0.5f + (top?(lDelta*(numRows/2)):0.0f); float rBase=(top?(cosf(lBase)*radius):0.0f); float zBase=(top?(sinf(lBase)*radius):-radius); float vBase=(top?(vDelta*(numRows/2)):0.0f); @@ -470,7 +470,7 @@ void BuildShapeGeometryVisitor::apply(const Sphere& sphere) bool drawFrontFace = _hints ? _hints->getCreateFrontFace() : true; bool drawBackFace = _hints ? _hints->getCreateBackFace() : false; - setMatrix(osg::Matrixd::translate(sphere.getCenter().x(),sphere.getCenter().y(),sphere.getCenter().z())); + setMatrix(Matrixd::translate(sphere.getCenter().x(),sphere.getCenter().y(),sphere.getCenter().z())); unsigned int numSegments = 40; unsigned int numRows = 20; @@ -484,15 +484,15 @@ void BuildShapeGeometryVisitor::apply(const Sphere& sphere) numSegments = MIN_NUM_SEGMENTS; } - float lDelta = osg::PIf/(float)numRows; + float lDelta = PIf/(float)numRows; float vDelta = 1.0f/(float)numRows; - float angleDelta = osg::PIf*2.0f/(float)numSegments; + float angleDelta = PIf*2.0f/(float)numSegments; float texCoordHorzDelta = 1.0f/(float)numSegments; if (drawBackFace) { - float lBase=-osg::PIf*0.5f; + float lBase=-PIf*0.5f; float rBase=0.0f; float zBase=-sphere.getRadius(); float vBase=0.0f; @@ -559,7 +559,7 @@ void BuildShapeGeometryVisitor::apply(const Sphere& sphere) if (drawFrontFace) { - float lBase=-osg::PIf*0.5f; + float lBase=-PIf*0.5f; float rBase=0.0f; float zBase=-sphere.getRadius(); float vBase=0.0f; @@ -774,7 +774,7 @@ void BuildShapeGeometryVisitor::apply(const Cone& cone) float normalRatio = 1.0f/(sqrtf(1.0f+normalz*normalz)); normalz *= normalRatio; - float angleDelta = 2.0f*osg::PIf/(float)numSegments; + float angleDelta = 2.0f*PIf/(float)numSegments; float texCoordHorzDelta = 1.0/(float)numSegments; float texCoordRowDelta = 1.0/(float)numRows; float hDelta = cone.getHeight()/(float)numRows; @@ -830,7 +830,7 @@ void BuildShapeGeometryVisitor::apply(const Cone& cone) if (createBottom) { Begin(GL_TRIANGLE_FAN); - angle = osg::PIf*2.0f; + angle = PIf*2.0f; texCoord = 1.0f; basez = cone.getBaseOffset(); @@ -880,7 +880,7 @@ void BuildShapeGeometryVisitor::apply(const Cylinder& cylinder) if (createBody) drawCylinderBody(numSegments, cylinder.getRadius(), cylinder.getHeight()); - float angleDelta = 2.0f*osg::PIf/(float)numSegments; + float angleDelta = 2.0f*PIf/(float)numSegments; float texCoordDelta = 1.0f/(float)numSegments; float r = cylinder.getRadius(); @@ -933,7 +933,7 @@ void BuildShapeGeometryVisitor::apply(const Cylinder& cylinder) TexCoord2f(0.5f,0.5f); Vertex3f(0.0f,0.0f,basez); - angle = osg::PIf*2.0f; + angle = PIf*2.0f; texCoord = 1.0f; for(unsigned int bottomi=0; bottomigetNumElements();i+=3) { - const osg::Vec3& v1=(*vertices)[indices->index(i)]; - const osg::Vec3& v2=(*vertices)[indices->index(i+1)]; - const osg::Vec3& v3=(*vertices)[indices->index(i+2)]; + const Vec3& v1=(*vertices)[indices->index(i)]; + const Vec3& v2=(*vertices)[indices->index(i+1)]; + const Vec3& v3=(*vertices)[indices->index(i+2)]; Vec3 normal = (v2-v1)^(v3-v2); normal.normalize(); @@ -1187,3 +1187,40 @@ void BuildShapeGeometryVisitor::apply(const CompositeShape& group) group.getChild(i)->accept(*this); } } + +Geometry* osg::convertShapeToGeometry(const Shape& shape, const TessellationHints* hints) +{ + ref_ptr geometry = new Geometry; + + BuildShapeGeometryVisitor buildGeometry(geometry.get(), hints); + shape.accept( buildGeometry ); + + return geometry.release(); +} + +Geometry* osg::convertShapeToGeometry(const Shape& shape, const TessellationHints* hints, const Vec4& color, Array::Binding colorBinding) +{ + ref_ptr geometry = convertShapeToGeometry(shape, hints); + + unsigned int numColors = 0; + switch(colorBinding) + { + case(Array::BIND_OVERALL): numColors = 1; break; + case(Array::BIND_PER_VERTEX): numColors = geometry->getVertexArray()->getNumElements(); break; + case(Array::BIND_PER_PRIMITIVE_SET): numColors = geometry->getPrimitiveSetList().size(); break; + default: break; + } + + if (numColors>0) + { + ref_ptr colors = new Vec4Array(colorBinding); + geometry->setColorArray(colors); + + for(unsigned int i=0; ipush_back(color); + } + } + + return geometry.release(); +}