From da84f9b4aa994a8731e0d17d1793c33d19da1241 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Wed, 30 Oct 2002 13:27:15 +0000 Subject: [PATCH] Added first cut of new primtive shapes support. --- Make/debugtests.bat | 4 + Make/makedirdefs | 1 + Make/osgtests.bat | 3 + VisualStudio/Demos/osgshape/osgshape.dsp | 95 +++ VisualStudio/VisualStudio.dsw | 27 + include/osg/CopyOp | 25 +- include/osg/Drawable | 58 +- include/osg/ProceduralGeometry | 150 +++++ include/osg/Shape | 517 +++++++++++++++++ src/Demos/osgshape/Makefile | 15 + src/Demos/osgshape/Makefile.inst | 11 + src/Demos/osgshape/osgshape.cpp | 78 +++ src/osg/CopyOp.cpp | 10 + src/osg/Drawable.cpp | 5 +- src/osg/Makefile | 2 + src/osg/ProceduralGeometry.cpp | 701 +++++++++++++++++++++++ src/osg/Shape.cpp | 5 + 17 files changed, 1674 insertions(+), 33 deletions(-) create mode 100755 VisualStudio/Demos/osgshape/osgshape.dsp create mode 100644 include/osg/ProceduralGeometry create mode 100644 include/osg/Shape create mode 100644 src/Demos/osgshape/Makefile create mode 100644 src/Demos/osgshape/Makefile.inst create mode 100644 src/Demos/osgshape/osgshape.cpp create mode 100644 src/osg/ProceduralGeometry.cpp create mode 100644 src/osg/Shape.cpp diff --git a/Make/debugtests.bat b/Make/debugtests.bat index 12023ea72..89db5b967 100755 --- a/Make/debugtests.bat +++ b/Make/debugtests.bat @@ -34,6 +34,10 @@ echo sgv Town.osg sgv Town.osg more memleaks.log +echo osgshape +osgshape +more memleaks.log + echo osganimate osganimate more memleaks.log diff --git a/Make/makedirdefs b/Make/makedirdefs index 6c0836042..0d2371d77 100644 --- a/Make/makedirdefs +++ b/Make/makedirdefs @@ -91,6 +91,7 @@ DEMOS_DIRS = \ osgscribe\ osgstereoimage\ osgsequence\ + osgshape\ osgteapot\ osgtext\ osgtexture1D\ diff --git a/Make/osgtests.bat b/Make/osgtests.bat index 01b5154fe..196903ebf 100755 --- a/Make/osgtests.bat +++ b/Make/osgtests.bat @@ -22,6 +22,9 @@ sgv cube_mapped_torus.osg echo sgv Town.osg sgv Town.osg +echo osgshape +osgshape + echo osganimate osganimate diff --git a/VisualStudio/Demos/osgshape/osgshape.dsp b/VisualStudio/Demos/osgshape/osgshape.dsp new file mode 100755 index 000000000..b64d2438b --- /dev/null +++ b/VisualStudio/Demos/osgshape/osgshape.dsp @@ -0,0 +1,95 @@ +# Microsoft Developer Studio Project File - Name="Demo osgshape" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=Demo osgshape - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "osgshape.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "osgshape.mak" CFG="Demo osgshape - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Demo osgshape - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "Demo osgshape - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "Demo osgshape - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GR /GX /O2 /I "../../../include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 /nologo /subsystem:console /pdb:none /machine:I386 /out:"../../../bin/osgshape.exe" /libpath:"../../../lib" + +!ELSEIF "$(CFG)" == "Demo osgshape - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MDd /W3 /Gm /vd0 /GR /GX /Zi /Od /I "../../../include" /D "_CONSOLE" /D "_MBCS" /D "FL_DLL" /D "WIN32" /D "_DEBUG" /FR /YX /FD /c +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 /nologo /subsystem:console /debug /machine:I386 /nodefaultlib:"libcmt" /out:"../../../bin/osgshaped.exe" /pdbtype:sept /libpath:"../../../lib" +# SUBTRACT LINK32 /incremental:no + +!ENDIF + +# Begin Target + +# Name "Demo osgshape - Win32 Release" +# Name "Demo osgshape - Win32 Debug" +# Begin Source File + +SOURCE=..\..\..\src\Demos\osgshape\osgshape.cpp +# End Source File +# End Target +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Project diff --git a/VisualStudio/VisualStudio.dsw b/VisualStudio/VisualStudio.dsw index efafb1971..b565ac5dc 100644 --- a/VisualStudio/VisualStudio.dsw +++ b/VisualStudio/VisualStudio.dsw @@ -381,6 +381,33 @@ Package=<4> ############################################################################### +Project: "Demo osgshape"=.\Demos\osgshape\osgshape.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name Core osg + End Project Dependency + Begin Project Dependency + Project_Dep_Name Core osgDB + End Project Dependency + Begin Project Dependency + Project_Dep_Name Core osgGA + End Project Dependency + Begin Project Dependency + Project_Dep_Name Core osgGLUT + End Project Dependency + Begin Project Dependency + Project_Dep_Name Core osgUtil + End Project Dependency +}}} + +############################################################################### + Project: "Demo osgcubemap"=.\Demos\osgcubemap\osgcubemap.dsp - Package Owner=<4> Package=<5> diff --git a/include/osg/CopyOp b/include/osg/CopyOp index ffd986756..c06937f96 100644 --- a/include/osg/CopyOp +++ b/include/osg/CopyOp @@ -20,6 +20,7 @@ class Node; class Drawable; class Array; class PrimitiveSet; +class Shape; /** Copy Op(erator) used to control the whether shallow or deep copy is used * during copy construction and clone operation.*/ @@ -30,17 +31,18 @@ class SG_EXPORT CopyOp enum Options { - SHALLOW_COPY = 0, - DEEP_COPY_OBJECTS = 1, - DEEP_COPY_NODES = 2, - DEEP_COPY_DRAWABLES = 4, - DEEP_COPY_STATESETS = 8, - DEEP_COPY_STATEATTRIBUTES = 16, - DEEP_COPY_TEXTURES = 32, - DEEP_COPY_IMAGES = 64, - DEEP_COPY_ARRAYS = 128, - DEEP_COPY_PRIMITIVES = 256, - DEEP_COPY_ALL = 0xffffffff + SHALLOW_COPY = 0, + DEEP_COPY_OBJECTS = 1, + DEEP_COPY_NODES = 2, + DEEP_COPY_DRAWABLES = 4, + DEEP_COPY_STATESETS = 8, + DEEP_COPY_STATEATTRIBUTES = 16, + DEEP_COPY_TEXTURES = 32, + DEEP_COPY_IMAGES = 64, + DEEP_COPY_ARRAYS = 128, + DEEP_COPY_PRIMITIVES = 256, + DEEP_COPY_SHAPES = 512, + DEEP_COPY_ALL = 0xffffffff }; typedef unsigned int CopyFlags; @@ -58,6 +60,7 @@ class SG_EXPORT CopyOp virtual Image* operator() (const Image* image) const; virtual Array* operator() (const Array* array) const; virtual PrimitiveSet* operator() (const PrimitiveSet* primitives) const; + virtual Shape* operator() (const Shape* shape) const; protected: diff --git a/include/osg/Drawable b/include/osg/Drawable index 87e9aec39..1c970944d 100644 --- a/include/osg/Drawable +++ b/include/osg/Drawable @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -20,7 +21,6 @@ class Vec2; class Vec3; class Vec4; class UByte4; -class Node; class Geometry; // this is define to alter the way display lists are compiled inside the @@ -57,6 +57,7 @@ class SG_EXPORT Drawable : public Object * Equivalent to dynamic_cast(this).*/ virtual const Geometry* asGeometry() const { return 0; } + /** A vector of osg::Node pointers which is used to store the parent(s) of drawable.*/ typedef std::vector ParentList; @@ -103,6 +104,36 @@ class SG_EXPORT Drawable : public Object StateSet* getOrCreateStateSet(); + /** Dirty the bounding box, forcing a computeBound() on the next call + * to getBound(). Should be called in the internal geometry of the Drawable + * is modified.*/ + void dirtyBound(); + + /** get bounding box of geoset. + * Note, now made virtual to make it possible to implement user-drawn + * objects albeit so what crudely, to be improved later. + */ + inline const BoundingBox& getBound() const + { + if( !_bbox_computed) + computeBound(); + return _bbox; + } + + + /** Set the Shape of the drawable. The shape can be used to + * speed up collision detection or as a guide for produral + * geometry generation - see osg::ProduralGeometry.*/ + inline void setShape(Shape* shape) { _shape = shape; } + + /** Get the Shape of the Drawable.*/ + inline Shape* getShape() { return _shape.get(); } + + /** Get the const Shape of the const Drawable.*/ + inline const Shape* getShape() const { return _shape.get(); } + + + /** Set the drawable to it can or cannot be used in conjunction with OpenGL * display lists. With set to true, calls to Drawable::setUseDisplayList, * whereas when set to false, no display lists can be created and calls @@ -126,23 +157,8 @@ class SG_EXPORT Drawable : public Object /** Force a recompile on next draw() of any OpenGL display list associated with this geoset.*/ void dirtyDisplayList(); - - - /** Dirty the bounding box, forcing a computeBound() on the next call - * to getBound(). Should be called in the internal geometry of the Drawable - * is modified.*/ - void dirtyBound(); - /** get bounding box of geoset. - * Note, now made virtual to make it possible to implement user-drawn - * objects albeit so what crudely, to be improved later. - */ - inline const BoundingBox& getBound() const - { - if( !_bbox_computed) - computeBound(); - return _bbox; - } + /** draw OpenGL primitives. * If the drawable has _useDisplayList set to true then use an OpenGL display @@ -315,15 +331,17 @@ class SG_EXPORT Drawable : public Object ref_ptr _stateset; + mutable BoundingBox _bbox; + mutable bool _bbox_computed; + + ref_ptr _shape; + bool _supportsDisplayList; bool _useDisplayList; typedef std::vector GLObjectList; mutable GLObjectList _globjList; - mutable BoundingBox _bbox; - mutable bool _bbox_computed; - ref_ptr _appCallback; ref_ptr _drawCallback; ref_ptr _cullCallback; diff --git a/include/osg/ProceduralGeometry b/include/osg/ProceduralGeometry new file mode 100644 index 000000000..fb23696a8 --- /dev/null +++ b/include/osg/ProceduralGeometry @@ -0,0 +1,150 @@ +//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_ProceduralGeometry +#define OSG_ProceduralGeometry 1 + +#include +#include +#include +#include +#include +#include + +namespace osg { + +class TessellationHints : public Object +{ + public: + + TessellationHints(): + _TessellationMode(USE_SHAPE_DEFAULTS), + _targetNumFaces(100), + _createFrontFace(true), + _createBackFace(false), + _createNormals(true), + _createTextureCoords(false), + _createTop(true), + _createBody(true), + _createBottom(true) {} + + + TessellationHints(const TessellationHints& tess, const CopyOp& copyop=CopyOp::SHALLOW_COPY): + Object(tess,copyop), + _TessellationMode(tess._TessellationMode), + _targetNumFaces(tess._targetNumFaces), + _createFrontFace(tess._createFrontFace), + _createBackFace(tess._createBackFace), + _createNormals(tess._createNormals), + _createTextureCoords(tess._createTextureCoords), + _createTop(tess._createTop), + _createBody(tess._createBody), + _createBottom(tess._createBottom) {} + + META_Object(osg,TessellationHints) + + + enum TessellationMode + { + USE_SHAPE_DEFAULTS, + USE_TARGET_NUM_FACES + }; + + inline void setTessellationMode(TessellationMode mode) { _TessellationMode=mode; } + inline TessellationMode getTessellationMode() const { return _TessellationMode; } + + inline void setTargetNumFaces(unsigned int target) { _targetNumFaces=target; } + inline unsigned int getTargetNumFaces() const { return _targetNumFaces; } + + inline void setCreateFrontFace(bool on) { _createFrontFace=on; } + inline bool getCreateFrontFace() const { return _createFrontFace; } + + inline void setCreateBackFace(bool on) { _createFrontFace=on; } + inline bool getCreateBackFace() const { return _createFrontFace; } + + inline void setCreateNormals(bool on) { _createNormals=on; } + inline bool getCreateNormals() const { return _createNormals; } + + inline void setCreateTextureCoords(bool on) { _createTextureCoords=on; } + inline bool getCreateTextureCoords() const { return _createTextureCoords; } + + inline void setCreateTop(bool on) { _createTop=on; } + inline bool getCreateTop() const { return _createTop; } + + inline void setCreateBody(bool on) { _createBody=on; } + inline bool getCreateBody() const { return _createBody; } + + inline void setCreateBottom(bool on) { _createBottom=on; } + inline bool getCreateBottom() const { return _createBottom; } + + protected: + + ~TessellationHints() {} + + + TessellationMode _TessellationMode; + unsigned int _targetNumFaces; + + bool _createFrontFace; + bool _createBackFace; + bool _createNormals; + bool _createTextureCoords; + + bool _createTop; + bool _createBody; + bool _createBottom; + +}; + +class SG_EXPORT ProceduralGeometry : public Drawable +{ + public: + + ProceduralGeometry(); + + ProceduralGeometry(Shape* shape); + + /** Copy constructor using CopyOp to manage deep vs shallow copy.*/ + ProceduralGeometry(const ProceduralGeometry& pg,const CopyOp& copyop=CopyOp::SHALLOW_COPY); + + virtual Object* cloneType() const { return osgNew ProceduralGeometry(); } + virtual Object* clone(const CopyOp& copyop) const { return osgNew ProceduralGeometry(*this,copyop); } + 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 "ProceduralGeometry"; } + + + void setTessellationHints(TessellationHints* hints) { _tessellationHints = hints; } + TessellationHints* getTessellationHints() { return _tessellationHints.get(); } + const TessellationHints* getTessellationHints() const { return _tessellationHints.get(); } + + + /** draw ProceduralGeometry directly ignoring an OpenGL display list which could be attached. + * This is the internal draw method which does the drawing itself, + * and is the method to override when deriving from ProceduralGeometry for user-drawn objects. + */ + virtual void drawImmediateMode(State& state); + + /** accept an AttributeFunctor and call its methods to tell it about the interal attributes that this Drawable has.*/ + virtual void accept(AttributeFunctor& af); + + /** accept a PrimtiveFunctor and call its methods to tell it about the interal primtives that this Drawable has.*/ + virtual void accept(PrimitiveFunctor& pf); + + protected: + + ProceduralGeometry& operator = (const ProceduralGeometry&) { return *this;} + + virtual ~ProceduralGeometry(); + + virtual bool computeBound() const; + + ref_ptr _tessellationHints; + +}; + + +} + +#endif diff --git a/include/osg/Shape b/include/osg/Shape new file mode 100644 index 000000000..54392b46f --- /dev/null +++ b/include/osg/Shape @@ -0,0 +1,517 @@ +//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 HeightField : public Shape +{ + public: + + HeightField() {} + + HeightField(const HeightField& mesh,const CopyOp& copyop=CopyOp::SHALLOW_COPY): + Shape(mesh,copyop), + _zeroRotation(true), + _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 "HeightFiled"; } + virtual void accept(osg::ShapeVisitor& sv) { sv.apply(*this); } + virtual void accept(osg::ConstShapeVisitor& csv) const { csv.apply(*this); } + + virtual void setNumColumnsAndRows(unsigned int col,unsigned int rows) = 0; + + 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 void setHeight(unsigned int c,unsigned int r) const = 0; + virtual float getHeight(unsigned int c,unsigned int r) const = 0; + + virtual void setNormal(unsigned int c,unsigned int r,const osg::Vec3& normal) const = 0; + virtual Vec3 getNormal(unsigned int c,unsigned int r) const = 0; + + inline Vec3 getVertex(unsigned int c,unsigned int r) const + { + return Vec3(_origin.x()+_dx*(float)c, + _origin.y()+_dy*(float)r, + _origin.z()+getHeight(c,r)); + } + + 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() {} + + bool _zeroRotation; + + unsigned int _columns,_rows; + + osg::Vec3 _origin; + float _dx; + float _dy; + + Quat _rotation; + +}; + +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); + + protected: + + ~CompositeShape() {} + + ref_ptr _shape; + ChildList _children; + +}; + +} + +#endif diff --git a/src/Demos/osgshape/Makefile b/src/Demos/osgshape/Makefile new file mode 100644 index 000000000..c9fe8c5d4 --- /dev/null +++ b/src/Demos/osgshape/Makefile @@ -0,0 +1,15 @@ +TOPDIR = ../../.. +include $(TOPDIR)/Make/makedefs + +CXXFILES =\ + osgshape.cpp\ + +LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS) + +INSTFILES = \ + $(CXXFILES)\ + Makefile.inst=Makefile + +EXEC = osgshape + +include $(TOPDIR)/Make/makerules diff --git a/src/Demos/osgshape/Makefile.inst b/src/Demos/osgshape/Makefile.inst new file mode 100644 index 000000000..05c41c748 --- /dev/null +++ b/src/Demos/osgshape/Makefile.inst @@ -0,0 +1,11 @@ +TOPDIR = ../.. +include $(TOPDIR)/Make/makedefs + +CXXFILES =\ + osgshape.cpp\ + +LIBS += $(OSG_LIBS) $(GLUT_LIB) $(GL_LIBS) $(X_LIBS) $(OTHER_LIBS) + +EXEC = osgshape + +include $(TOPDIR)/Make/makerules diff --git a/src/Demos/osgshape/osgshape.cpp b/src/Demos/osgshape/osgshape.cpp new file mode 100644 index 000000000..8a9f8be52 --- /dev/null +++ b/src/Demos/osgshape/osgshape.cpp @@ -0,0 +1,78 @@ +#include +#include +#include +#include + +#include + +#include +#include + +#include + +#include + +osg::Geode* createShapes() +{ + osg::Geode* geode = osgNew osg::Geode(); + + // --------------------------------------- + // Set up a StateSet to make the cube red + // --------------------------------------- + osg::StateSet* stateset = osgNew osg::StateSet(); + + + osg::Image* image = osgDB::readImageFile("lz.rgb"); + if (image) + { + osg::Texture2D* texture = osgNew osg::Texture2D; + texture->setImage(image); + stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON); + } + + geode->setStateSet( stateset ); + + float radius = 0.8f; + float height = 1.0f; + + geode->addDrawable(new osg::ProceduralGeometry(osgNew osg::Sphere(osg::Vec3(0.0f,0.0f,0.0f),radius))); + geode->addDrawable(new osg::ProceduralGeometry(osgNew osg::Box(osg::Vec3(2.0f,0.0f,0.0f),2*radius))); + geode->addDrawable(new osg::ProceduralGeometry(osgNew osg::Cone(osg::Vec3(4.0f,0.0f,0.0f),radius,height))); + geode->addDrawable(new osg::ProceduralGeometry(osgNew osg::Cylinder(osg::Vec3(6.0f,0.0f,0.0f),radius,height))); + + return geode; +} + +int main( int argc, char **argv ) +{ + + glutInit( &argc, argv ); + + // create the commandline args. + std::vector commandLine; + for(int i=1;i #include #include +#include using namespace osg; @@ -92,3 +93,12 @@ PrimitiveSet* CopyOp::operator() (const PrimitiveSet* primitive) const else return const_cast(primitive); } + +Shape* CopyOp::operator() (const Shape* shape) const +{ + if (shape && _flags&DEEP_COPY_SHAPES) + return dynamic_cast(shape->clone(*this)); + else + return const_cast(shape); +} + diff --git a/src/osg/Drawable.cpp b/src/osg/Drawable.cpp index 6ecb6b9bd..3ed69667a 100644 --- a/src/osg/Drawable.cpp +++ b/src/osg/Drawable.cpp @@ -33,11 +33,12 @@ Drawable::Drawable(const Drawable& drawable,const CopyOp& copyop): Object(drawable,copyop), _parents(), // leave empty as parentList is managed by Geode _stateset(copyop(drawable._stateset.get())), + _bbox(drawable._bbox), + _bbox_computed(drawable._bbox_computed), + _shape(copyop(drawable._shape.get())), _supportsDisplayList(drawable._supportsDisplayList), _useDisplayList(drawable._useDisplayList), _globjList(drawable._globjList), - _bbox(drawable._bbox), - _bbox_computed(drawable._bbox_computed), _drawCallback(drawable._drawCallback), _cullCallback(drawable._cullCallback) {} diff --git a/src/osg/Makefile b/src/osg/Makefile index d35574bbe..e699146b5 100644 --- a/src/osg/Makefile +++ b/src/osg/Makefile @@ -62,11 +62,13 @@ CXXFILES =\ PolygonStipple.cpp\ PositionAttitudeTransform.cpp\ PrimitiveSet.cpp\ + ProceduralGeometry.cpp\ Projection.cpp\ Quat.cpp\ Sequence.cpp\ ShadeModel.cpp\ ShadowVolumeOccluder.cpp\ + Shape.cpp\ State.cpp\ StateSet.cpp\ Stencil.cpp\ diff --git a/src/osg/ProceduralGeometry.cpp b/src/osg/ProceduralGeometry.cpp new file mode 100644 index 000000000..ecdefaf33 --- /dev/null +++ b/src/osg/ProceduralGeometry.cpp @@ -0,0 +1,701 @@ +#include +#include + +using namespace osg; + +/////////////////////////////////////////////////////////////////////////////// +// +// draw shape +// + +class DrawShapeVisitor : public ConstShapeVisitor +{ + public: + + DrawShapeVisitor(State& state,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; + 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; + rowiaccept(dsv); + } +} + +void ProceduralGeometry::accept(AttributeFunctor& af) +{ +} + +void ProceduralGeometry::accept(PrimitiveFunctor& pf) +{ +} + + +bool ProceduralGeometry::computeBound() const +{ + + if (_shape.valid()) + { + ComputeBoundShapeVisitor cbsv(_bbox); + _shape->accept(cbsv); + _bbox_computed = true; + return true; + } + + return false; +} + diff --git a/src/osg/Shape.cpp b/src/osg/Shape.cpp new file mode 100644 index 000000000..37a418d57 --- /dev/null +++ b/src/osg/Shape.cpp @@ -0,0 +1,5 @@ +#include + + + +