1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield 2 * 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. 7 * 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. 12*/ 13 14#ifndef OSG_SHAPE 15#define OSG_SHAPE 1 16 17#include <osg/Object> 18#include <osg/Vec3> 19#include <osg/Quat> 20#include <osg/Plane> 21#include <osg/Array> 22 23namespace osg { 24 25// forward declare visitors. 26class ShapeVisitor; 27class ConstShapeVisitor; 28 29 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 34 * subclasses.*/ 35#define META_Shape(library,name) \ 36 virtual osg::Object* cloneType() const { return new name(); } \ 37 virtual osg::Object* clone(const osg::CopyOp& copyop) const { return new name (*this,copyop); } \ 38 virtual bool isSameKindAs(const osg::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(osg::ShapeVisitor& sv) { sv.apply(*this); } \ 42 virtual void accept(osg::ConstShapeVisitor& csv) const { csv.apply(*this); } 43 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. 47*/ 48class OSG_EXPORT Shape : public Object 49{ 50 public: 51 52 Shape() {} 53 54 Shape(const Shape& sa,const CopyOp& copyop=CopyOp::SHALLOW_COPY): 55 Object(sa,copyop) {} 56 57 /** Clone the type of an attribute, with Object* return type. 58 Must be defined by derived classes.*/ 59 virtual Object* cloneType() const = 0; 60 61 /** Clone an attribute, with Object* return type. 62 Must be defined by derived classes.*/ 63 virtual Object* clone(const CopyOp&) const = 0; 64 65 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; } 68 69 /** return the name of the attribute's library.*/ 70 virtual const char* libraryName() const { return "osg"; } 71 72 /** return the name of the attribute's class type.*/ 73 virtual const char* className() const { return "Shape"; } 74 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; 78 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; 82 83 protected: 84 85 virtual ~Shape(); 86}; 87 88// forward declarations of Shape types. 89class Sphere; 90class Box; 91class Cone; 92class Cylinder; 93class Capsule; 94class InfinitePlane; 95 96class TriangleMesh; 97class ConvexHull; 98class HeightField; 99 100class CompositeShape; 101 102class OSG_EXPORT ShapeVisitor 103{ 104 public: 105 106 ShapeVisitor() {} 107 virtual ~ShapeVisitor(); 108 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&) {} 116 117 virtual void apply(TriangleMesh&) {} 118 virtual void apply(ConvexHull&) {} 119 virtual void apply(HeightField&) {} 120 121 virtual void apply(CompositeShape&) {} 122}; 123 124class OSG_EXPORT ConstShapeVisitor 125{ 126 public: 127 128 ConstShapeVisitor() {} 129 virtual ~ConstShapeVisitor(); 130 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&) {} 138 139 virtual void apply(const TriangleMesh&) {} 140 virtual void apply(const ConvexHull&) {} 141 virtual void apply(const HeightField&) {} 142 143 virtual void apply(const CompositeShape&) {} 144}; 145 146class OSG_EXPORT Sphere : public Shape 147{ 148 public: 149 150 Sphere(): 151 _center(0.0f,0.0f,0.0f), 152 _radius(1.0f) {} 153 154 Sphere(const osg::Vec3& center,float radius): 155 _center(center), 156 _radius(radius) {} 157 158 Sphere(const Sphere& sphere,const CopyOp& copyop=CopyOp::SHALLOW_COPY): 159 Shape(sphere,copyop), 160 _center(sphere._center), 161 _radius(sphere._radius) {} 162 163 META_Shape(osg, Sphere); 164 165 inline bool valid() const { return _radius>=0.0f; } 166 167 inline void set(const Vec3& center,float radius) 168 { 169 _center = center; 170 _radius = radius; 171 } 172 173 inline void setCenter(const Vec3& center) { _center = center; } 174 inline const Vec3& getCenter() const { return _center; } 175 176 inline void setRadius(float radius) { _radius = radius; } 177 inline float getRadius() const { return _radius; } 178 179 protected: 180 181 virtual ~Sphere(); 182 183 Vec3 _center; 184 float _radius; 185 186}; 187 188class OSG_EXPORT Box : public Shape 189{ 190 public: 191 192 Box(): 193 _center(0.0f,0.0f,0.0f), 194 _halfLengths(0.5f,0.5f,0.5f) {} 195 196 Box(const osg::Vec3& center,float width): 197 _center(center), 198 _halfLengths(width*0.5f,width*0.5f,width*0.5f) {} 199 200 Box(const osg::Vec3& center,float lengthX,float lengthY, float lengthZ): 201 _center(center), 202 _halfLengths(lengthX*0.5f,lengthY*0.5f,lengthZ*0.5f) {} 203 204 Box(const Box& box,const CopyOp& copyop=CopyOp::SHALLOW_COPY): 205 Shape(box,copyop), 206 _center(box._center), 207 _halfLengths(box._halfLengths), 208 _rotation(box._rotation) {} 209 210 META_Shape(osg, Box); 211 212 inline bool valid() const { return _halfLengths.x()>=0.0f; } 213 214 inline void set(const Vec3& center,const Vec3& halfLengths) 215 { 216 _center = center; 217 _halfLengths = halfLengths; 218 } 219 220 inline void setCenter(const Vec3& center) { _center = center; } 221 inline const Vec3& getCenter() const { return _center; } 222 223 inline void setHalfLengths(const Vec3& halfLengths) { _halfLengths = halfLengths; } 224 inline const Vec3& getHalfLengths() const { return _halfLengths; } 225 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(); } 230 231 protected: 232 233 virtual ~Box(); 234 235 Vec3 _center; 236 Vec3 _halfLengths; 237 Quat _rotation; 238 239}; 240 241 242 243class OSG_EXPORT Cone : public Shape 244{ 245 public: 246 247 Cone(): 248 _center(0.0f,0.0f,0.0f), 249 _radius(1.0f), 250 _height(1.0f) {} 251 252 Cone(const osg::Vec3& center,float radius,float height): 253 _center(center), 254 _radius(radius), 255 _height(height) {} 256 257 Cone(const Cone& cone,const CopyOp& copyop=CopyOp::SHALLOW_COPY): 258 Shape(cone,copyop), 259 _center(cone._center), 260 _radius(cone._radius), 261 _height(cone._height), 262 _rotation(cone._rotation) {} 263 264 META_Shape(osg, Cone); 265 266 inline bool valid() const { return _radius>=0.0f; } 267 268 inline void set(const Vec3& center,float radius, float height) 269 { 270 _center = center; 271 _radius = radius; 272 _height = height; 273 } 274 275 inline void setCenter(const Vec3& center) { _center = center; } 276 inline const Vec3& getCenter() const { return _center; } 277 278 inline void setRadius(float radius) { _radius = radius; } 279 inline float getRadius() const { return _radius; } 280 281 inline void setHeight(float height) { _height = height; } 282 inline float getHeight() const { return _height; } 283 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(); } 288 289 inline float getBaseOffsetFactor() const { return 0.25f; } 290 inline float getBaseOffset() const { return -getBaseOffsetFactor()*getHeight(); } 291 292 protected: 293 294 virtual ~Cone(); 295 296 Vec3 _center; 297 float _radius; 298 float _height; 299 300 Quat _rotation; 301}; 302 303class OSG_EXPORT Cylinder : public Shape 304{ 305 public: 306 307 Cylinder(): 308 _center(0.0f,0.0f,0.0f), 309 _radius(1.0f), 310 _height(1.0f) {} 311 312 Cylinder(const osg::Vec3& center,float radius,float height): 313 _center(center), 314 _radius(radius), 315 _height(height) {} 316 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) {} 323 324 META_Shape(osg, Cylinder); 325 326 inline bool valid() const { return _radius>=0.0f; } 327 328 inline void set(const Vec3& center,float radius, float height) 329 { 330 _center = center; 331 _radius = radius; 332 _height = height; 333 } 334 335 inline void setCenter(const Vec3& center) { _center = center; } 336 inline const Vec3& getCenter() const { return _center; } 337 338 inline void setRadius(float radius) { _radius = radius; } 339 inline float getRadius() const { return _radius; } 340 341 inline void setHeight(float height) { _height = height; } 342 inline float getHeight() const { return _height; } 343 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(); } 348 349 protected: 350 351 virtual ~Cylinder(); 352 353 Vec3 _center; 354 float _radius; 355 float _height; 356 Quat _rotation; 357}; 358 359class OSG_EXPORT Capsule : public Shape 360{ 361 public: 362 363 Capsule(): 364 _center(0.0f,0.0f,0.0f), 365 _radius(1.0f), 366 _height(1.0f) {} 367 368 Capsule(const osg::Vec3& center,float radius,float height): 369 _center(center), 370 _radius(radius), 371 _height(height) {} 372 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) {} 379 380 META_Shape(osg, Capsule); 381 382 inline bool valid() const { return _radius>=0.0f; } 383 384 inline void set(const Vec3& center,float radius, float height) 385 { 386 _center = center; 387 _radius = radius; 388 _height = height; 389 } 390 391 inline void setCenter(const Vec3& center) { _center = center; } 392 inline const Vec3& getCenter() const { return _center; } 393 394 inline void setRadius(float radius) { _radius = radius; } 395 inline float getRadius() const { return _radius; } 396 397 inline void setHeight(float height) { _height = height; } 398 inline float getHeight() const { return _height; } 399 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(); } 404 405 protected: 406 407 virtual ~Capsule(); 408 409 Vec3 _center; 410 float _radius; 411 float _height; 412 Quat _rotation; 413}; 414 415class OSG_EXPORT InfinitePlane : public Shape, public Plane 416{ 417 public: 418 InfinitePlane() {} 419 420 InfinitePlane(const InfinitePlane& plane,const CopyOp& copyop=CopyOp::SHALLOW_COPY): 421 Shape(plane,copyop), 422 Plane(plane) {} 423 424 META_Shape(osg, InfinitePlane); 425 426 protected: 427 428 virtual ~InfinitePlane(); 429}; 430 431/** Exists to support collision detection engines not for doing rendering, use \ref osg::Geometry instead. 432 */ 433class OSG_EXPORT TriangleMesh : public Shape 434{ 435 public: 436 437 TriangleMesh() {} 438 439 TriangleMesh(const TriangleMesh& mesh,const CopyOp& copyop=CopyOp::SHALLOW_COPY): 440 Shape(mesh,copyop), 441 _vertices(mesh._vertices), 442 _indices(mesh._indices) {} 443 444 META_Shape(osg, TriangleMesh); 445 446 447 void setVertices(Vec3Array* vertices) { _vertices = vertices; } 448 Vec3Array* getVertices() { return _vertices.get(); } 449 const Vec3Array* getVertices() const { return _vertices.get(); } 450 451 452 void setIndices(IndexArray* indices) { _indices = indices; } 453 IndexArray* getIndices() { return _indices.get(); } 454 const IndexArray* getIndices() const { return _indices.get(); } 455 456 protected: 457 458 virtual ~TriangleMesh(); 459 460 ref_ptr<Vec3Array> _vertices; 461 ref_ptr<IndexArray> _indices; 462 463}; 464 465class OSG_EXPORT ConvexHull : public TriangleMesh 466{ 467 public: 468 469 ConvexHull() {} 470 471 ConvexHull(const ConvexHull& hull,const CopyOp& copyop=CopyOp::SHALLOW_COPY): 472 TriangleMesh(hull,copyop) {} 473 474 META_Shape(osg, TriangleMesh); 475 476 protected: 477 478 virtual ~ConvexHull(); 479}; 480 481class OSG_EXPORT HeightField : public Shape 482{ 483 public: 484 485 HeightField(); 486 487 HeightField(const HeightField& mesh,const CopyOp& copyop=CopyOp::SHALLOW_COPY); 488 489 META_Shape(osg, HeightField); 490 491 typedef std::vector<float> HeightList; 492 493 void allocate(unsigned int numColumns,unsigned int numRows); 494 495 inline unsigned int getNumColumns() const { return _columns; } 496 inline unsigned int getNumRows() const { return _rows; } 497 498 inline void setOrigin(const osg::Vec3& origin) { _origin = origin; } 499 inline const osg::Vec3& getOrigin() const { return _origin; } 500 501 inline void setXInterval(float dx) { _dx = dx; } 502 inline float getXInterval() const { return _dx; } 503 504 inline void setYInterval(float dy) { _dy = dy; } 505 inline float getYInterval() const { return _dy; } 506 507 /** Get the FloatArray height data.*/ 508 osg::FloatArray* getFloatArray() { return _heights.get(); } 509 510 /** Get the const FloatArray height data.*/ 511 const osg::FloatArray* getFloatArray() const { return _heights.get(); } 512 513 HeightList& getHeightList() { return _heights->asVector(); } 514 515 const HeightList& getHeightList() const { return _heights->asVector(); } 516 517 /** Set the height of the skirt to render around the edge of HeightField. 518 * The skirt is used as a means of disguising edge boundaries between adjacent HeightField, 519 * particularly of ones with different resolutions.*/ 520 void setSkirtHeight(float skirtHeight) { _skirtHeight = skirtHeight; } 521 522 /** Get the height of the skirt to render around the edge of HeightField.*/ 523 float getSkirtHeight() const { return _skirtHeight; } 524 525 /** Set the width in number of cells in from the edge that the height field should be rendered from. 526 * This exists to allow gradient and curvature continutity to be maintained between adjacent HeightField, where 527 * the border cells will overlap adjacent HeightField.*/ 528 void setBorderWidth(unsigned int borderWidth) { _borderWidth = borderWidth; } 529 530 /** Get the width in number of cells in from the edge that the height field should be rendered from.*/ 531 unsigned int getBorderWidth() const { return _borderWidth; } 532 533 inline void setRotation(const Quat& quat) { _rotation = quat; } 534 inline const Quat& getRotation() const { return _rotation; } 535 inline Matrix computeRotationMatrix() const { return Matrix(_rotation); } 536 inline bool zeroRotation() const { return _rotation.zeroRotation(); } 537 538 /* set a single height point in the height field */ 539 inline void setHeight(unsigned int c,unsigned int r,float value) 540 { 541 (*_heights)[c+r*_columns] = value; 542 } 543 544 /* Get address of single height point in the height field, allows user to change. */ 545 inline float& getHeight(unsigned int c,unsigned int r) 546 { 547 return (*_heights)[c+r*_columns]; 548 } 549 550 /* Get value of single height point in the height field, not editable. */ 551 inline float getHeight(unsigned int c,unsigned int r) const 552 { 553 return (*_heights)[c+r*_columns]; 554 } 555 556 inline Vec3 getVertex(unsigned int c,unsigned int r) const 557 { 558 return Vec3(_origin.x()+getXInterval()*(float)c, 559 _origin.y()+getYInterval()*(float)r, 560 _origin.z()+(*_heights)[c+r*_columns]); 561 } 562 563 Vec3 getNormal(unsigned int c,unsigned int r) const; 564 565 Vec2 getHeightDelta(unsigned int c,unsigned int r) const; 566 567 protected: 568 569 virtual ~HeightField(); 570 571 unsigned int _columns,_rows; 572 573 osg::Vec3 _origin; // _origin is the min value of the X and Y coordinates. 574 float _dx; 575 float _dy; 576 577 float _skirtHeight; 578 unsigned int _borderWidth; 579 580 Quat _rotation; 581 osg::ref_ptr<osg::FloatArray> _heights; 582 583}; 584 585typedef HeightField Grid; 586 587 588class OSG_EXPORT CompositeShape : public Shape 589{ 590 public: 591 592 593 594 typedef std::vector< ref_ptr<Shape> > ChildList; 595 596 CompositeShape() {} 597 598 CompositeShape(const CompositeShape& cs,const CopyOp& copyop=CopyOp::SHALLOW_COPY): 599 Shape(cs,copyop), 600 _children(cs._children) {} 601 602 META_Shape(osg, CompositeShape); 603 604 /** Set the shape that encloses all of the children.*/ 605 void setShape(Shape* shape) { _shape = shape; } 606 607 /** Get the shape that encloses all of the children.*/ 608 Shape* getShape() { return _shape.get(); } 609 610 /** Get the const shape that encloses all of the children.*/ 611 const Shape* getShape() const { return _shape.get(); } 612 613 /** Get the number of children of this composite shape.*/ 614 unsigned int getNumChildren() const { return static_cast<unsigned int>(_children.size()); } 615 616 /** Get a child.*/ 617 Shape* getChild(unsigned int i) { return _children[i].get(); } 618 619 /** Get a const child.*/ 620 const Shape* getChild(unsigned int i) const { return _children[i].get(); } 621 622 /** Add a child to the list.*/ 623 void addChild(Shape* shape) { _children.push_back(shape); } 624 625 template<class T> void addChild( const ref_ptr<T>& child ) { addChild(child.get()); } 626 627 /** remove a child from the list.*/ 628 void removeChild(unsigned int i) { _children.erase(_children.begin()+i); } 629 630 /** find the index number of child, if child is not found then it returns getNumChildren(), 631 * so should be used in similar style to STL's result!=end().*/ 632 unsigned int findChildNo(Shape* shape) const 633 { 634 for (unsigned int childNo=0;childNo<_children.size();++childNo) 635 { 636 if (_children[childNo]==shape) return childNo; 637 } 638 return static_cast<unsigned int>(_children.size()); // node not found. 639 640 } 641 642 protected: 643 644 virtual ~CompositeShape(); 645 646 ref_ptr<Shape> _shape; 647 ChildList _children; 648 649}; 650 651} 652 653#endif 654