1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
3 * This library is open source and may be redistributed and/or modified under
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version. The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * OpenSceneGraph Public License for more details.
25// forward declare visitors.
27class ConstShapeVisitor;
30/** META_StateAttribute macro define the standard clone, isSameKindAs,
31 * className and getType methods.
32 * Use when subclassing from Object to make it more convenient to define
33 * the standard pure virtual methods which are required for all Object
35#define META_Shape(library,name) \
36 virtual Object* cloneType() const { return new name(); } \
37 virtual Object* clone(const CopyOp& copyop) const { return new name (*this,copyop); } \
38 virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast<const name *>(obj)!=NULL; } \
39 virtual const char* libraryName() const { return #library; } \
40 virtual const char* className() const { return #name; } \
41 virtual void accept(ShapeVisitor& sv) { sv.apply(*this); } \
42 virtual void accept(ConstShapeVisitor& csv) const { csv.apply(*this); }
44/** Base class for all shape types.
45 * Shapes are used to either for culling and collision detection or
46 * to define the geometric shape of procedurally generate Geometry.
48class OSG_EXPORT Shape : public Object
54 Shape(const Shape& sa,const CopyOp& copyop=CopyOp::SHALLOW_COPY):
57 /** Clone the type of an attribute, with Object* return type.
58 Must be defined by derived classes.*/
59 virtual Object* cloneType() const = 0;
61 /** Clone an attribute, with Object* return type.
62 Must be defined by derived classes.*/
63 virtual Object* clone(const CopyOp&) const = 0;
66 /** return true if this and obj are of the same kind of object.*/
67 virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast<const Shape*>(obj)!=NULL; }
69 /** return the name of the attribute's library.*/
70 virtual const char* libraryName() const { return "osg"; }
72 /** return the name of the attribute's class type.*/
73 virtual const char* className() const { return "Shape"; }
75 /** accept a non const shape visitor which can be used on non const shape objects.
76 Must be defined by derived classes.*/
77 virtual void accept(ShapeVisitor&)=0;
79 /** accept a const shape visitor which can be used on const shape objects.
80 Must be defined by derived classes.*/
81 virtual void accept(ConstShapeVisitor&) const =0;
88// forward declarations of Shape types.
102class OSG_EXPORT ShapeVisitor
107 virtual ~ShapeVisitor();
109 virtual void apply(Shape&) {}
110 virtual void apply(Sphere&) {}
111 virtual void apply(Box&) {}
112 virtual void apply(Cone&) {}
113 virtual void apply(Cylinder&) {}
114 virtual void apply(Capsule&) {}
115 virtual void apply(InfinitePlane&) {}
117 virtual void apply(TriangleMesh&) {}
118 virtual void apply(ConvexHull&) {}
119 virtual void apply(HeightField&) {}
121 virtual void apply(CompositeShape&) {}
124class OSG_EXPORT ConstShapeVisitor
128 ConstShapeVisitor() {}
129 virtual ~ConstShapeVisitor();
131 virtual void apply(const Shape&) {}
132 virtual void apply(const Sphere&) {}
133 virtual void apply(const Box&) {}
134 virtual void apply(const Cone&) {}
135 virtual void apply(const Cylinder&) {}
136 virtual void apply(const Capsule&) {}
137 virtual void apply(const InfinitePlane&) {}
139 virtual void apply(const TriangleMesh&) {}
140 virtual void apply(const ConvexHull&) {}
141 virtual void apply(const HeightField&) {}
143 virtual void apply(const CompositeShape&) {}
146class OSG_EXPORT Sphere : public Shape
151 _center(0.0f,0.0f,0.0f),
154 Sphere(const Vec3& center,float radius):
158 Sphere(const Sphere& sphere,const CopyOp& copyop=CopyOp::SHALLOW_COPY):
159 Shape(sphere,copyop),
160 _center(sphere._center),
161 _radius(sphere._radius) {}
163 META_Shape(osg, Sphere);
165 inline bool valid() const { return _radius>=0.0f; }
167 inline void set(const Vec3& center,float radius)
173 inline void setCenter(const Vec3& center) { _center = center; }
174 inline const Vec3& getCenter() const { return _center; }
176 inline void setRadius(float radius) { _radius = radius; }
177 inline float getRadius() const { return _radius; }
188class OSG_EXPORT Box : public Shape
193 _center(0.0f,0.0f,0.0f),
194 _halfLengths(0.5f,0.5f,0.5f) {}
196 Box(const Vec3& center,float width):
198 _halfLengths(width*0.5f,width*0.5f,width*0.5f) {}
200 Box(const Vec3& center,float lengthX,float lengthY, float lengthZ):
202 _halfLengths(lengthX*0.5f,lengthY*0.5f,lengthZ*0.5f) {}
204 Box(const Box& box,const CopyOp& copyop=CopyOp::SHALLOW_COPY):
206 _center(box._center),
207 _halfLengths(box._halfLengths),
208 _rotation(box._rotation) {}
210 META_Shape(osg, Box);
212 inline bool valid() const { return _halfLengths.x()>=0.0f; }
214 inline void set(const Vec3& center,const Vec3& halfLengths)
217 _halfLengths = halfLengths;
220 inline void setCenter(const Vec3& center) { _center = center; }
221 inline const Vec3& getCenter() const { return _center; }
223 inline void setHalfLengths(const Vec3& halfLengths) { _halfLengths = halfLengths; }
224 inline const Vec3& getHalfLengths() const { return _halfLengths; }
226 inline void setRotation(const Quat& quat) { _rotation = quat; }
227 inline const Quat& getRotation() const { return _rotation; }
228 inline Matrix computeRotationMatrix() const { return Matrix(_rotation); }
229 inline bool zeroRotation() const { return _rotation.zeroRotation(); }
243class OSG_EXPORT Cone : public Shape
248 _center(0.0f,0.0f,0.0f),
252 Cone(const Vec3& center,float radius,float height):
257 Cone(const Cone& cone,const CopyOp& copyop=CopyOp::SHALLOW_COPY):
259 _center(cone._center),
260 _radius(cone._radius),
261 _height(cone._height),
262 _rotation(cone._rotation) {}
264 META_Shape(osg, Cone);
266 inline bool valid() const { return _radius>=0.0f; }
268 inline void set(const Vec3& center,float radius, float height)
275 inline void setCenter(const Vec3& center) { _center = center; }
276 inline const Vec3& getCenter() const { return _center; }
278 inline void setRadius(float radius) { _radius = radius; }
279 inline float getRadius() const { return _radius; }
281 inline void setHeight(float height) { _height = height; }
282 inline float getHeight() const { return _height; }
284 inline void setRotation(const Quat& quat) { _rotation = quat; }
285 inline const Quat& getRotation() const { return _rotation; }
286 inline Matrix computeRotationMatrix() const { return Matrix(_rotation); }
287 inline bool zeroRotation() const { return _rotation.zeroRotation(); }
289 inline float getBaseOffsetFactor() const { return 0.25f; }
290 inline float getBaseOffset() const { return -getBaseOffsetFactor()*getHeight(); }
303class OSG_EXPORT Cylinder : public Shape
308 _center(0.0f,0.0f,0.0f),
312 Cylinder(const Vec3& center,float radius,float height):
317 Cylinder(const Cylinder& cylinder,const CopyOp& copyop=CopyOp::SHALLOW_COPY):
318 Shape(cylinder,copyop),
319 _center(cylinder._center),
320 _radius(cylinder._radius),
321 _height(cylinder._height),
322 _rotation(cylinder._rotation) {}
324 META_Shape(osg, Cylinder);
326 inline bool valid() const { return _radius>=0.0f; }
328 inline void set(const Vec3& center,float radius, float height)
335 inline void setCenter(const Vec3& center) { _center = center; }
336 inline const Vec3& getCenter() const { return _center; }
338 inline void setRadius(float radius) { _radius = radius; }
339 inline float getRadius() const { return _radius; }
341 inline void setHeight(float height) { _height = height; }
342 inline float getHeight() const { return _height; }
344 inline void setRotation(const Quat& quat) { _rotation = quat; }
345 inline const Quat& getRotation() const { return _rotation; }
346 inline Matrix computeRotationMatrix() const { return Matrix(_rotation); }
347 bool zeroRotation() const { return _rotation.zeroRotation(); }
359class OSG_EXPORT Capsule : public Shape
364 _center(0.0f,0.0f,0.0f),
368 Capsule(const Vec3& center,float radius,float height):
373 Capsule(const Capsule& capsule,const CopyOp& copyop=CopyOp::SHALLOW_COPY):
374 Shape(capsule,copyop),
375 _center(capsule._center),
376 _radius(capsule._radius),
377 _height(capsule._height),
378 _rotation(capsule._rotation) {}
380 META_Shape(osg, Capsule);
382 inline bool valid() const { return _radius>=0.0f; }
384 inline void set(const Vec3& center,float radius, float height)
391 inline void setCenter(const Vec3& center) { _center = center; }
392 inline const Vec3& getCenter() const { return _center; }
394 inline void setRadius(float radius) { _radius = radius; }
395 inline float getRadius() const { return _radius; }
397 inline void setHeight(float height) { _height = height; }
398 inline float getHeight() const { return _height; }
400 inline void setRotation(const Quat& quat) { _rotation = quat; }
401 inline const Quat& getRotation() const { return _rotation; }
402 inline Matrix computeRotationMatrix() const { return Matrix(_rotation); }
403 bool zeroRotation() const { return _rotation.zeroRotation(); }
416class OSG_EXPORT InfinitePlane : public Shape, public Plane
421 InfinitePlane(const InfinitePlane& plane,const CopyOp& copyop=CopyOp::SHALLOW_COPY):
425 META_Shape(osg, InfinitePlane);
429 virtual ~InfinitePlane();
433class OSG_EXPORT TriangleMesh : public Shape
439 TriangleMesh(const TriangleMesh& mesh,const CopyOp& copyop=CopyOp::SHALLOW_COPY):
441 _vertices(mesh._vertices),
442 _indices(mesh._indices) {}
444 META_Shape(osg, TriangleMesh);
447 void setVertices(Vec3Array* vertices) { _vertices = vertices; }
448 Vec3Array* getVertices() { return _vertices.get(); }
449 const Vec3Array* getVertices() const { return _vertices.get(); }
452 void setIndices(IndexArray* indices) { _indices = indices; }
453 IndexArray* getIndices() { return _indices.get(); }
454 const IndexArray* getIndices() const { return _indices.get(); }
458 virtual ~TriangleMesh();
460 ref_ptr<Vec3Array> _vertices;
461 ref_ptr<IndexArray> _indices;
466class OSG_EXPORT ConvexHull : public TriangleMesh
472 ConvexHull(const ConvexHull& hull,const CopyOp& copyop=CopyOp::SHALLOW_COPY):
473 TriangleMesh(hull,copyop) {}
475 META_Shape(osg, ConvexHull);
479 virtual ~ConvexHull();
482class OSG_EXPORT HeightField : public Shape
488 HeightField(const HeightField& mesh,const CopyOp& copyop=CopyOp::SHALLOW_COPY);
490 META_Shape(osg, HeightField);
492 typedef std::vector<float> HeightList;
494 void allocate(unsigned int numColumns,unsigned int numRows);
496 inline unsigned int getNumColumns() const { return _columns; }
497 inline unsigned int getNumRows() const { return _rows; }
499 inline void setOrigin(const Vec3& origin) { _origin = origin; }
500 inline const Vec3& getOrigin() const { return _origin; }
502 inline void setXInterval(float dx) { _dx = dx; }
503 inline float getXInterval() const { return _dx; }
505 inline void setYInterval(float dy) { _dy = dy; }
506 inline float getYInterval() const { return _dy; }
508 /** Get the FloatArray height data.*/
509 FloatArray* getFloatArray() { return _heights.get(); }
511 /** Get the const FloatArray height data.*/
512 const FloatArray* getFloatArray() const { return _heights.get(); }
514 HeightList& getHeightList() { return _heights->asVector(); }
516 const HeightList& getHeightList() const { return _heights->asVector(); }
518 /** Set the height of the skirt to render around the edge of HeightField.
519 * The skirt is used as a means of disguising edge boundaries between adjacent HeightField,
520 * particularly of ones with different resolutions.*/
521 void setSkirtHeight(float skirtHeight) { _skirtHeight = skirtHeight; }
523 /** Get the height of the skirt to render around the edge of HeightField.*/
524 float getSkirtHeight() const { return _skirtHeight; }
526 /** Set the width in number of cells in from the edge that the height field should be rendered from.
527 * This exists to allow gradient and curvature continutity to be maintained between adjacent HeightField, where
528 * the border cells will overlap adjacent HeightField.*/
529 void setBorderWidth(unsigned int borderWidth) { _borderWidth = borderWidth; }
531 /** Get the width in number of cells in from the edge that the height field should be rendered from.*/
532 unsigned int getBorderWidth() const { return _borderWidth; }
534 inline void setRotation(const Quat& quat) { _rotation = quat; }
535 inline const Quat& getRotation() const { return _rotation; }
536 inline Matrix computeRotationMatrix() const { return Matrix(_rotation); }
537 inline bool zeroRotation() const { return _rotation.zeroRotation(); }
539 /* set a single height point in the height field */
540 inline void setHeight(unsigned int c,unsigned int r,float value)
542 (*_heights)[c+r*_columns] = value;
545 /* Get address of single height point in the height field, allows user to change. */
546 inline float& getHeight(unsigned int c,unsigned int r)
548 return (*_heights)[c+r*_columns];
551 /* Get value of single height point in the height field, not editable. */
552 inline float getHeight(unsigned int c,unsigned int r) const
554 return (*_heights)[c+r*_columns];
557 inline Vec3 getVertex(unsigned int c,unsigned int r) const
559 return Vec3(_origin.x()+getXInterval()*(float)c,
560 _origin.y()+getYInterval()*(float)r,
561 _origin.z()+(*_heights)[c+r*_columns]);
564 Vec3 getNormal(unsigned int c,unsigned int r) const;
566 Vec2 getHeightDelta(unsigned int c,unsigned int r) const;
570 virtual ~HeightField();
572 unsigned int _columns,_rows;
574 Vec3 _origin; // _origin is the min value of the X and Y coordinates.
579 unsigned int _borderWidth;
582 ref_ptr<FloatArray> _heights;
586typedef HeightField Grid;
590class OSG_EXPORT CompositeShape : public Shape
596 typedef std::vector< ref_ptr<Shape> > ChildList;
600 CompositeShape(const CompositeShape& cs,const CopyOp& copyop=CopyOp::SHALLOW_COPY):
602 _children(cs._children) {}
604 META_Shape(osg, CompositeShape);
606 /** Set the shape that encloses all of the children.*/
607 void setShape(Shape* shape) { _shape = shape; }
609 /** Get the shape that encloses all of the children.*/
610 Shape* getShape() { return _shape.get(); }
612 /** Get the const shape that encloses all of the children.*/
613 const Shape* getShape() const { return _shape.get(); }
615 /** Get the number of children of this composite shape.*/
616 unsigned int getNumChildren() const { return static_cast<unsigned int>(_children.size()); }
619 Shape* getChild(unsigned int i) { return _children[i].get(); }
621 /** Get a const child.*/
622 const Shape* getChild(unsigned int i) const { return _children[i].get(); }
624 /** Add a child to the list.*/
625 void addChild(Shape* shape) { _children.push_back(shape); }
627 template<class T> void addChild( const ref_ptr<T>& child ) { addChild(child.get()); }
629 /** remove a child from the list.*/
630 void removeChild(unsigned int i) { _children.erase(_children.begin()+i); }
632 /** find the index number of child, if child is not found then it returns getNumChildren(),
633 * so should be used in similar style to STL's result!=end().*/
634 unsigned int findChildNo(Shape* shape) const
636 for (unsigned int childNo=0;childNo<_children.size();++childNo)
638 if (_children[childNo]==shape) return childNo;
640 return static_cast<unsigned int>(_children.size()); // node not found.
646 virtual ~CompositeShape();
648 ref_ptr<Shape> _shape;
654/** Describe several hints that can be passed to a Tessellator (like the one used
655 * by \c ShapeDrawable) as a mean to try to influence the way it works.
657class TessellationHints : public Object
662 _TessellationMode(USE_SHAPE_DEFAULTS),
664 _targetNumFaces(100),
665 _createFrontFace(true),
666 _createBackFace(false),
667 _createNormals(true),
668 _createTextureCoords(false),
671 _createBottom(true) {}
674 TessellationHints(const TessellationHints& tess, const CopyOp& copyop=CopyOp::SHALLOW_COPY):
676 _TessellationMode(tess._TessellationMode),
677 _detailRatio(tess._detailRatio),
678 _targetNumFaces(tess._targetNumFaces),
679 _createFrontFace(tess._createFrontFace),
680 _createBackFace(tess._createBackFace),
681 _createNormals(tess._createNormals),
682 _createTextureCoords(tess._createTextureCoords),
683 _createTop(tess._createTop),
684 _createBody(tess._createBody),
685 _createBottom(tess._createBottom) {}
687 META_Object(osg,TessellationHints);
690 enum TessellationMode
696 inline void setTessellationMode(TessellationMode mode) { _TessellationMode=mode; }
697 inline TessellationMode getTessellationMode() const { return _TessellationMode; }
699 inline void setDetailRatio(float ratio) { _detailRatio = ratio; }
700 inline float getDetailRatio() const { return _detailRatio; }
702 inline void setTargetNumFaces(unsigned int target) { _targetNumFaces=target; }
703 inline unsigned int getTargetNumFaces() const { return _targetNumFaces; }
705 inline void setCreateFrontFace(bool on) { _createFrontFace=on; }
706 inline bool getCreateFrontFace() const { return _createFrontFace; }
708 inline void setCreateBackFace(bool on) { _createBackFace=on; }
709 inline bool getCreateBackFace() const { return _createBackFace; }
711 inline void setCreateNormals(bool on) { _createNormals=on; }
712 inline bool getCreateNormals() const { return _createNormals; }
714 inline void setCreateTextureCoords(bool on) { _createTextureCoords=on; }
715 inline bool getCreateTextureCoords() const { return _createTextureCoords; }
717 inline void setCreateTop(bool on) { _createTop=on; }
718 inline bool getCreateTop() const { return _createTop; }
720 inline void setCreateBody(bool on) { _createBody=on; }
721 inline bool getCreateBody() const { return _createBody; }
723 inline void setCreateBottom(bool on) { _createBottom=on; }
724 inline bool getCreateBottom() const { return _createBottom; }
728 ~TessellationHints() {}
731 TessellationMode _TessellationMode;
734 unsigned int _targetNumFaces;
736 bool _createFrontFace;
737 bool _createBackFace;
739 bool _createTextureCoords;
750/** Convenience class for populating an Geometry with vertex, normals, texture coords and primitives that can render a Shape. */
751class OSG_EXPORT BuildShapeGeometryVisitor : public ConstShapeVisitor
755 BuildShapeGeometryVisitor(Geometry* geometry, const TessellationHints* hints);
757 virtual void apply(const Sphere&);
758 virtual void apply(const Box&);
759 virtual void apply(const Cone&);
760 virtual void apply(const Cylinder&);
761 virtual void apply(const Capsule&);
762 virtual void apply(const InfinitePlane&);
764 virtual void apply(const TriangleMesh&);
765 virtual void apply(const ConvexHull&);
766 virtual void apply(const HeightField&);
768 virtual void apply(const CompositeShape&);
770 void Normal(const Vec3f& v) { _normals->push_back(v); }
771 void Normal3f(float x, float y, float z) { Normal(Vec3(x,y,z)); }
773 void TexCoord(const Vec2f& tc) { _texcoords->push_back(tc); }
774 void TexCoord2f(float x, float y) { TexCoord(Vec2(x,y)); }
776 void Vertex(const Vec3f& v);
777 void Vertex3f(float x, float y, float z) { Vertex(Vec3(x,y,z)); }
779 void setMatrix(const Matrixd& m);
781 void Begin(GLenum mode);
786 BuildShapeGeometryVisitor& operator = (const BuildShapeGeometryVisitor&) { return *this; }
788 enum SphereHalf { SphereTopHalf, SphereBottomHalf };
790 // helpers for apply( Cylinder | Sphere | Capsule )
791 void drawCylinderBody(unsigned int numSegments, float radius, float height);
792 void drawHalfSphere(unsigned int numSegments, unsigned int numRows, float radius, SphereHalf which, float zOffset = 0.0f);
795 const TessellationHints* _hints;
797 ref_ptr<Vec3Array> _vertices;
798 ref_ptr<Vec3Array> _normals;
799 ref_ptr<Vec2Array> _texcoords;
802 unsigned int _start_index;
807extern OSG_EXPORT Geometry* convertShapeToGeometry(const Shape& shape, const TessellationHints* hints);
809extern OSG_EXPORT Geometry* convertShapeToGeometry(const Shape& shape, const TessellationHints* hints, const Vec4& color, Array::Binding colorBinding=Array::BIND_OVERALL);