//C++ header - Open Scene Graph - Copyright (C) 1998-2002 Robert Osfield //Distributed under the terms of the GNU Library General Public License (LGPL) //as published by the Free Software Foundation. #ifndef OSG_SHAPE #define OSG_SHAPE 1 #include #include #include #include #include namespace osg { // forward decare visitors. class ShapeVisitor; class ConstShapeVisitor; /** META_StateAttribute macro define the standard clone, isSameKindAs, * className and getType methods. * Use when subclassing from Object to make it more convinient to define * the standard pure virtual methods which are required for all Object * subclasses.*/ #define META_Shape(library,name) \ virtual osg::Object* cloneType() const { return osgNew name(); } \ virtual osg::Object* clone(const osg::CopyOp& copyop) const { return osgNew name (*this,copyop); } \ virtual bool isSameKindAs(const osg::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); } /** Base class for all shape types. * Shapes are used to either for culling and collision detection or * to define the geometric shape of procedurally generate Geometry. */ class SG_EXPORT Shape : public Object { public: Shape() {} Shape(const Shape& sa,const CopyOp& copyop=CopyOp::SHALLOW_COPY): Object(sa,copyop) {} /** Clone the type of an attribute, with Object* return type. Must be defined by derived classes.*/ virtual Object* cloneType() const = 0; /** Clone an attribute, with Object* return type. Must be defined by derived classes.*/ virtual Object* clone(const CopyOp&) const = 0; /** return true if this and obj are of the same kind of object.*/ virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast(obj)!=NULL; } /** return the name of the attribute's library.*/ virtual const char* libraryName() const { return "osg"; } /** return the name of the attribute's class type.*/ virtual const char* className() const { return "Shape"; } /** accept a non const shape visitor which can be used on non const shape objects. Must be defined by derived classes.*/ virtual void accept(ShapeVisitor&)=0; /** accept a const shape visitor which can be used on const shape objects. Must be defined by derived classes.*/ virtual void accept(ConstShapeVisitor&) const =0; }; // forward declartions of Shape types. class Sphere; class Box; class Cone; class Cylinder; class InfinitePlane; class TriangleMesh; class ConvexHull; class HeightField; class CompositeShape; class ShapeVisitor { public: ShapeVisitor() {} virtual void apply(Sphere&) {} virtual void apply(Box&) {} virtual void apply(Cone&) {} virtual void apply(Cylinder&) {} virtual void apply(InfinitePlane&) {} virtual void apply(TriangleMesh&) {} virtual void apply(ConvexHull&) {} virtual void apply(HeightField&) {} virtual void apply(CompositeShape&) {} }; class ConstShapeVisitor { public: ConstShapeVisitor() {} 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&) {} }; class Sphere : public Shape { public: Sphere(): _center(0.0f,0.0f,0.0f), _radius(1.0f) {} Sphere(const osg::Vec3& center,float radius): _center(center), _radius(radius) {} Sphere(const Sphere& sphere,const CopyOp& copyop=CopyOp::SHALLOW_COPY): Shape(sphere,copyop), _center(sphere._center), _radius(sphere._radius) {} META_Shape(osg, Sphere) inline bool valid() const { return _radius>=0.0f; } inline void set(const Vec3& center,float radius) { _center = center; _radius = radius; } inline void setCenter(const Vec3& center) { _center = center; } inline const Vec3& getCenter() const { return _center; } inline void setRadius(float radius) { _radius = radius; } inline float getRadius() const { return _radius; } protected: virtual ~Sphere() {} Vec3 _center; float _radius; }; class Box : public Shape { public: Box(): _center(0.0f,0.0f,0.0f), _halfLengths(0.5f,0.5f,0.5f) {} Box(const osg::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): _center(center), _halfLengths(lengthX*0.5f,lengthY*0.5f,lengthZ*0.5f) {} Box(const Box& box,const CopyOp& copyop=CopyOp::SHALLOW_COPY): Shape(box,copyop), _center(box._center), _halfLengths(box._halfLengths), _rotation(box._rotation) {} META_Shape(osg, Box) inline bool valid() const { return _halfLengths.x()>=0.0f; } inline void set(const Vec3& center,const Vec3& halfLengths) { _center = center; _halfLengths = halfLengths; } inline void setCenter(const Vec3& center) { _center = center; } inline const Vec3& getCenter() const { return _center; } inline void setHalfLengths(const Vec3& halfLengths) { _halfLengths = halfLengths; } inline const Vec3& getHalfLengths() const { return _halfLengths; } inline void setRotation(const Quat& quat) { _rotation = quat; } inline const Quat& getRotation() const { return _rotation; } inline Matrix getRotationMatrix() const { Matrix matrix; _rotation.get(matrix); return matrix; } inline bool zeroRotation() const { return _rotation.zeroRotation(); } protected: virtual ~Box() {} Vec3 _center; Vec3 _halfLengths; Quat _rotation; }; class Cone : public Shape { public: Cone(): _center(0.0f,0.0f,0.0f), _radius(1.0f), _height(1.0f) {} Cone(const osg::Vec3& center,float radius,float height): _center(center), _radius(radius), _height(height) {} Cone(const Cone& cone,const CopyOp& copyop=CopyOp::SHALLOW_COPY): Shape(cone,copyop), _center(cone._center), _radius(cone._radius), _height(cone._height), _rotation(cone._rotation) {} META_Shape(osg, Cone) inline bool valid() const { return _radius>=0.0f; } inline void set(const Vec3& center,float radius, float height) { _center = center; _radius = radius; _height = height; } inline void setCenter(const Vec3& center) { _center = center; } inline const Vec3& getCenter() const { return _center; } inline void setRadius(float radius) { _radius = radius; } inline float getRadius() const { return _radius; } inline void setHeight(float height) { _height = height; } inline float getHeight() const { return _height; } inline void setRotation(const Quat& quat) { _rotation = quat; } inline const Quat& getRotation() const { return _rotation; } inline Matrix getRotationMatrix() const { Matrix matrix; _rotation.get(matrix); return matrix; } inline bool zeroRotation() const { return _rotation.zeroRotation(); } inline float getBaseOffsetFactor() const { return 0.25f; } inline float getBaseOffset() const { return -getBaseOffsetFactor()*getHeight(); } protected: virtual ~Cone() {} Vec3 _center; float _radius; float _height; Quat _rotation; }; class Cylinder : public Shape { public: Cylinder(): _center(0.0f,0.0f,0.0f), _radius(-1.0f), _height(0.0f) {} Cylinder(const osg::Vec3& center,float radius,float height): _center(center), _radius(radius), _height(height) {} Cylinder(const Cylinder& cylinder,const CopyOp& copyop=CopyOp::SHALLOW_COPY): Shape(cylinder,copyop), _center(cylinder._center), _radius(cylinder._radius), _height(cylinder._height), _rotation(cylinder._rotation) {} META_Shape(osg, Cylinder) inline bool valid() const { return _radius>=0.0f; } inline void set(const Vec3& center,float radius, float height) { _center = center; _radius = radius; _height = height; } inline void setCenter(const Vec3& center) { _center = center; } inline const Vec3& getCenter() const { return _center; } inline void setRadius(float radius) { _radius = radius; } inline float getRadius() const { return _radius; } inline void setHeight(float height) { _height = height; } inline float getHeight() const { return _height; } inline void setRotation(const Quat& quat) { _rotation = quat; } inline const Quat& getRotation() const { return _rotation; } inline Matrix getRotationMatrix() const { Matrix matrix; _rotation.get(matrix); return matrix; } bool zeroRotation() const { return _rotation.zeroRotation(); } protected: virtual ~Cylinder() {} Vec3 _center; float _radius; float _height; Quat _rotation; }; class InfinitePlane : public Shape, public Plane { public: }; class TriangleMesh : public Shape { public: TriangleMesh() {} TriangleMesh(const TriangleMesh& mesh,const CopyOp& copyop=CopyOp::SHALLOW_COPY): Shape(mesh,copyop), _vertices(mesh._vertices), _indices(mesh._indices) {} META_Shape(osg, TriangleMesh) void setVertices(Vec3Array* vertices) { _vertices = vertices; } Vec3Array* getVertices() { return _vertices.get(); } const Vec3Array* getVertices() const { return _vertices.get(); } void setIndices(IndexArray* indices) { _indices = indices; } IndexArray* getIndices() { return _indices.get(); } const IndexArray* getIndices() const { return _indices.get(); } protected: ~TriangleMesh() {} ref_ptr _vertices; ref_ptr _indices; }; class ConvexHull : public TriangleMesh { public: ConvexHull() {} ConvexHull(const ConvexHull& hull,const CopyOp& copyop=CopyOp::SHALLOW_COPY): TriangleMesh(hull,copyop) {} META_Shape(osg, TriangleMesh) protected: ~ConvexHull() {} }; class SG_EXPORT HeightField : public Shape { public: HeightField() {} HeightField(const HeightField& mesh,const CopyOp& copyop=CopyOp::SHALLOW_COPY): Shape(mesh,copyop), _columns(0), _rows(0), _origin(0.0f,0.0f,0.0f), _dx(1.0f), _dy(1.0f) {} virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast(obj)!=NULL; } virtual const char* libraryName() const { return "osg"; } virtual const char* className() const { return "HeightField"; } virtual void accept(osg::ShapeVisitor& sv) { sv.apply(*this); } virtual void accept(osg::ConstShapeVisitor& csv) const { csv.apply(*this); } 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 setXInterval(float dx) { _dx = dx; } inline float getXInterval() const { return _dx; } inline void setYInterval(float dy) { _dy = dy; } inline float getYInterval() const { return _dy; } virtual float getHeight(unsigned int c,unsigned int r) const = 0; virtual Vec3 getNormal(unsigned int c,unsigned int r) const; inline void setRotation(const Quat& quat) { _rotation = quat; } inline const Quat& getRotation() const { return _rotation; } inline Matrix getRotationMatrix() const { Matrix matrix; _rotation.get(matrix); return matrix; } inline bool zeroRotation() const { return _rotation.zeroRotation(); } protected: ~HeightField() {} unsigned int _columns,_rows; osg::Vec3 _origin; float _dx; float _dy; Quat _rotation; }; class SG_EXPORT Grid : public HeightField { public: Grid(); Grid(const Grid& mesh,const CopyOp& copyop=CopyOp::SHALLOW_COPY); META_Shape(osg,Grid) void allocateGrid(unsigned int numColumns,unsigned int numRows); void setHeight(unsigned int c,unsigned int r,float value) { _heights[c+r*_columns] = value; } virtual float getHeight(unsigned int c,unsigned int r) const { return _heights[c+r*_columns]; } protected: ~Grid(); typedef std::vector HeightList; HeightList _heights; }; class CompositeShape : public Shape { public: typedef std::vector< ref_ptr > ChildList; CompositeShape() {} CompositeShape(const CompositeShape& cs,const CopyOp& copyop=CopyOp::SHALLOW_COPY): Shape(cs,copyop), _children(cs._children) {} META_Shape(osg, CompositeShape) /** Set the shape that encloses all of the children.*/ void setShape(Shape* shape) { _shape = shape; } /** Get the shape that encloses all of the children.*/ Shape* getShape() { return _shape.get(); } /** Get the const shape that encloses all of the children.*/ const Shape* getShape() const { return _shape.get(); } /** Get the number of children of this composite shape.*/ unsigned int getNumChildren() const { return _children.size(); } /** Get a child.*/ Shape* getChild(unsigned int i) { return _children[i].get(); } /** Get a const child.*/ const Shape* getChild(unsigned int i) const { return _children[i].get(); } /** Add a child to the list.*/ void addChild(Shape* shape) { _children.push_back(shape); } /** remove a child from the list.*/ void removeChild(unsigned int i) { _children.erase(_children.begin()+i); } /** find the index number of child, if child is not found then it returns getNumChildren(), * so should be used in similar sytle of STL's result!=end().*/ unsigned int findChildNo(Shape* shape) const { for (unsigned int childNo=0;childNo<_children.size();++childNo) { if (_children[childNo]==shape) return childNo; } return _children.size(); // node not found. } protected: ~CompositeShape() {} ref_ptr _shape; ChildList _children; }; } #endif