#include #include using namespace osg; /////////////////////////////////////////////////////////////////////////////// // // draw shape // class DrawShapeVisitor : public ConstShapeVisitor { public: DrawShapeVisitor(State& state,const TessellationHints* hints): _state(state), _hints(hints) {} virtual void apply(const Sphere&); virtual void apply(const Box&); virtual void apply(const Cone&); virtual void apply(const Cylinder&); virtual void apply(const InfinitePlane&); virtual void apply(const TriangleMesh&); virtual void apply(const ConvexHull&); virtual void apply(const HeightField&); virtual void apply(const CompositeShape&); State& _state; const TessellationHints* _hints; }; void DrawShapeVisitor::apply(const Sphere& sphere) { glPushMatrix(); glTranslatef(sphere.getCenter().x(),sphere.getCenter().y(),sphere.getCenter().z()); unsigned int numSegments = 40; unsigned int numRows = 20; float lDelta = osg::PI/(float)numRows; float vDelta = 1.0f/(float)numRows; float angleDelta = osg::PI*2.0f/(float)numSegments; float texCoordHorzDelta = 1.0f/(float)numSegments; float lBase=-osg::PI*0.5f; float rBase=0.0f; float zBase=-sphere.getRadius(); float vBase=0.0f; float nzBase=-1.0f; float nRatioBase=0.0f; for(unsigned int rowi=0; rowigetNumElements();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)]; Vec3 normal = (v2-v1)^(v3-v2); normal.normalize(); glNormal3fv(normal.ptr()); glVertex3fv(v1.ptr()); glVertex3fv(v2.ptr()); glVertex3fv(v3.ptr()); } glEnd(); } } void DrawShapeVisitor::apply(const ConvexHull& hull) { apply((const TriangleMesh&)hull); } void DrawShapeVisitor::apply(const HeightField& field) { if (field.getNumColumns()==0 || field.getNumRows()==0) return; glPushMatrix(); glTranslatef(field.getOrigin().x(),field.getOrigin().y(),field.getOrigin().z()); if (!field.zeroRotation()) { Matrix rotation(field.getRotationMatrix()); glMultMatrixf(rotation.ptr()); } float dx = field.getXInterval(); float dy = field.getYInterval(); float du = 1.0f/((float)field.getNumColumns()-1.0f); float dv = 1.0f/((float)field.getNumRows()-1.0f); float vBase = 0.0f; for(unsigned int row=0;rowaccept(*this); } } /////////////////////////////////////////////////////////////////////////////// // // Compute bounding of shape // class ComputeBoundShapeVisitor : public ConstShapeVisitor { public: ComputeBoundShapeVisitor(BoundingBox& bb):_bb(bb) {} virtual void apply(const Sphere&); virtual void apply(const Box&); virtual void apply(const Cone&); virtual void apply(const Cylinder&); virtual void apply(const InfinitePlane&); virtual void apply(const TriangleMesh&); virtual void apply(const ConvexHull&); virtual void apply(const HeightField&); virtual void apply(const CompositeShape&); BoundingBox& _bb; }; void ComputeBoundShapeVisitor::apply(const Sphere& sphere) { Vec3 halfLengths(sphere.getRadius(),sphere.getRadius(),sphere.getRadius()); _bb.expandBy(sphere.getCenter()-halfLengths); _bb.expandBy(sphere.getCenter()+halfLengths); } void ComputeBoundShapeVisitor::apply(const Box& box) { if (box.zeroRotation()) { _bb.expandBy(box.getCenter()-box.getHalfLengths()); _bb.expandBy(box.getCenter()+box.getHalfLengths()); } else { float x = box.getHalfLengths().x(); float y = box.getHalfLengths().y(); float z = box.getHalfLengths().z(); Vec3 base_1(box.getCenter()+Vec3(-x,-y,-z)); Vec3 base_2(box.getCenter()+Vec3(x,-y,-z)); Vec3 base_3(box.getCenter()+Vec3(x,y,-z)); Vec3 base_4(box.getCenter()+Vec3(-x,y,-z)); Vec3 top_1(box.getCenter()+Vec3(-x,-y,z)); Vec3 top_2(box.getCenter()+Vec3(x,-y,z)); Vec3 top_3(box.getCenter()+Vec3(x,y,z)); Vec3 top_4(box.getCenter()+Vec3(-x,y,z)); Matrix matrix = box.getRotationMatrix(); _bb.expandBy(base_1*matrix); _bb.expandBy(base_2*matrix); _bb.expandBy(base_3*matrix); _bb.expandBy(base_4*matrix); _bb.expandBy(top_1*matrix); _bb.expandBy(top_2*matrix); _bb.expandBy(top_3*matrix); _bb.expandBy(top_4*matrix); } } void ComputeBoundShapeVisitor::apply(const Cone& cone) { if (cone.zeroRotation()) { _bb.expandBy(cone.getCenter()+Vec3(-cone.getRadius(),-cone.getRadius(),cone.getBaseOffset())); _bb.expandBy(cone.getCenter()+Vec3(cone.getRadius(),cone.getRadius(),cone.getHeight()+cone.getBaseOffset())); } else { Vec3 top(cone.getCenter()+Vec3(cone.getRadius(),cone.getRadius(),cone.getHeight()+cone.getBaseOffset())); Vec3 base_1(cone.getCenter()+Vec3(-cone.getRadius(),-cone.getRadius(),cone.getBaseOffset())); Vec3 base_2(cone.getCenter()+Vec3(cone.getRadius(),-cone.getRadius(),cone.getBaseOffset())); Vec3 base_3(cone.getCenter()+Vec3(cone.getRadius(),cone.getRadius(),cone.getBaseOffset())); Vec3 base_4(cone.getCenter()+Vec3(-cone.getRadius(),cone.getRadius(),cone.getBaseOffset())); Matrix matrix = cone.getRotationMatrix(); _bb.expandBy(base_1*matrix); _bb.expandBy(base_2*matrix); _bb.expandBy(base_3*matrix); _bb.expandBy(base_4*matrix); _bb.expandBy(top*matrix); } } void ComputeBoundShapeVisitor::apply(const Cylinder& cylinder) { if (cylinder.zeroRotation()) { Vec3 halfLengths(cylinder.getRadius(),cylinder.getRadius(),cylinder.getHeight()*0.5f); _bb.expandBy(cylinder.getCenter()-halfLengths); _bb.expandBy(cylinder.getCenter()+halfLengths); } else { float r = cylinder.getRadius(); float z = cylinder.getHeight()*0.5f; Vec3 base_1(cylinder.getCenter()+Vec3(-r,-r,-z)); Vec3 base_2(cylinder.getCenter()+Vec3(r,-r,-z)); Vec3 base_3(cylinder.getCenter()+Vec3(r,r,-z)); Vec3 base_4(cylinder.getCenter()+Vec3(-r,r,-z)); Vec3 top_1(cylinder.getCenter()+Vec3(-r,-r,z)); Vec3 top_2(cylinder.getCenter()+Vec3(r,-r,z)); Vec3 top_3(cylinder.getCenter()+Vec3(r,r,z)); Vec3 top_4(cylinder.getCenter()+Vec3(-r,r,z)); Matrix matrix = cylinder.getRotationMatrix(); _bb.expandBy(base_1*matrix); _bb.expandBy(base_2*matrix); _bb.expandBy(base_3*matrix); _bb.expandBy(base_4*matrix); _bb.expandBy(top_1*matrix); _bb.expandBy(top_2*matrix); _bb.expandBy(top_3*matrix); _bb.expandBy(top_4*matrix); } } void ComputeBoundShapeVisitor::apply(const InfinitePlane&) { // can't compute the bounding box of an infinite plane!!! :-) } void ComputeBoundShapeVisitor::apply(const TriangleMesh& mesh) { const Vec3Array* vertices = mesh.getVertices(); const IndexArray* indices = mesh.getIndices(); if (vertices && indices) { for(unsigned int i=0;igetNumElements();++i) { const osg::Vec3& v=(*vertices)[indices->index(i)]; _bb.expandBy(v); } } } void ComputeBoundShapeVisitor::apply(const ConvexHull& hull) { apply((const TriangleMesh&)hull); } void ComputeBoundShapeVisitor::apply(const HeightField& field) { float zMin=FLT_MAX; float zMax=-FLT_MAX; for(unsigned int row=0;rowzMax) zMax = z; } } if (field.zeroRotation()) { _bb.expandBy(field.getOrigin()+osg::Vec3(0.0f,0.0f,zMin)); _bb.expandBy(field.getOrigin()+osg::Vec3(field.getXInterval()*field.getNumColumns(),field.getYInterval()*field.getNumRows(),zMax)); } else { float x = field.getXInterval()*field.getNumColumns(); float y = field.getYInterval()*field.getNumRows(); Vec3 base_1(field.getOrigin()+Vec3(0,0,zMin)); Vec3 base_2(field.getOrigin()+Vec3(x,0,zMin)); Vec3 base_3(field.getOrigin()+Vec3(x,y,zMin)); Vec3 base_4(field.getOrigin()+Vec3(0,y,zMin)); Vec3 top_1(field.getOrigin()+Vec3(0,0,zMax)); Vec3 top_2(field.getOrigin()+Vec3(x,0,zMax)); Vec3 top_3(field.getOrigin()+Vec3(x,y,zMax)); Vec3 top_4(field.getOrigin()+Vec3(0,y,zMax)); Matrix matrix = field.getRotationMatrix(); _bb.expandBy(base_1*matrix); _bb.expandBy(base_2*matrix); _bb.expandBy(base_3*matrix); _bb.expandBy(base_4*matrix); _bb.expandBy(top_1*matrix); _bb.expandBy(top_2*matrix); _bb.expandBy(top_3*matrix); _bb.expandBy(top_4*matrix); } } void ComputeBoundShapeVisitor::apply(const CompositeShape& group) { for(unsigned int i=0;iaccept(*this); } } /////////////////////////////////////////////////////////////////////////////// // // Accept a primtive functor for each of the shapes. // class PrimitiveShapeVisitor : public ConstShapeVisitor { public: PrimitiveShapeVisitor(Drawable::PrimitiveFunctor& functor,const TessellationHints* hints): _functor(functor), _hints(hints) {} virtual void apply(const Sphere&); virtual void apply(const Box&); virtual void apply(const Cone&); virtual void apply(const Cylinder&); virtual void apply(const InfinitePlane&); virtual void apply(const TriangleMesh&); virtual void apply(const ConvexHull&); virtual void apply(const HeightField&); virtual void apply(const CompositeShape&); Drawable::PrimitiveFunctor& _functor; const TessellationHints* _hints; }; void PrimitiveShapeVisitor::apply(const Sphere& sphere) { float tx = sphere.getCenter().x(); float ty = sphere.getCenter().y(); float tz = sphere.getCenter().z(); unsigned int numSegments = 40; unsigned int numRows = 20; float lDelta = osg::PI/(float)numRows; float vDelta = 1.0f/(float)numRows; float angleDelta = osg::PI*2.0f/(float)numSegments; float texCoordHorzDelta = 1.0f/(float)numSegments; float lBase=-osg::PI*0.5f; float rBase=0.0f; float zBase=-sphere.getRadius(); float vBase=0.0f; float nzBase=-1.0f; float nRatioBase=0.0f; for(unsigned int rowi=0; rowigetNumElements();i+=3) { _functor.vertex((*vertices)[indices->index(i)]); _functor.vertex((*vertices)[indices->index(i+1)]); _functor.vertex((*vertices)[indices->index(i+2)]); } _functor.end(); } } void PrimitiveShapeVisitor::apply(const ConvexHull& hull) { apply((const TriangleMesh&)hull); } void PrimitiveShapeVisitor::apply(const HeightField& field) { if (field.getNumColumns()==0 || field.getNumRows()==0) return; Matrix matrix = field.getRotationMatrix(); matrix.setTrans(field.getOrigin()); float dx = field.getXInterval(); float dy = field.getYInterval(); for(unsigned int row=0;rowaccept(*this); } } /////////////////////////////////////////////////////////////////////////////// // // ProceduralGeometry itself.. // ProceduralGeometry::ProceduralGeometry() { } ProceduralGeometry::ProceduralGeometry(Shape* shape) { setShape(shape); } ProceduralGeometry::ProceduralGeometry(const ProceduralGeometry& pg,const CopyOp& copyop): Drawable(pg,copyop) { } ProceduralGeometry::~ProceduralGeometry() { } void ProceduralGeometry::drawImmediateMode(State& state) { if (_shape.valid()) { DrawShapeVisitor dsv(state,_tessellationHints.get()); _shape->accept(dsv); } } void ProceduralGeometry::accept(ConstAttributeFunctor&) const { } void ProceduralGeometry::accept(PrimitiveFunctor& pf) const { if (_shape.valid()) { PrimitiveShapeVisitor psv(pf,_tessellationHints.get()); _shape->accept(psv); } } bool ProceduralGeometry::computeBound() const { if (_shape.valid()) { ComputeBoundShapeVisitor cbsv(_bbox); _shape->accept(cbsv); _bbox_computed = true; return true; } return false; }