diff --git a/include/osgVolume/Brick b/include/osgVolume/Brick new file mode 100644 index 000000000..3b27b6835 --- /dev/null +++ b/include/osgVolume/Brick @@ -0,0 +1,158 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2008 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * OpenSceneGraph Public License for more details. +*/ + +#ifndef OSGVOLUME_BRICK +#define OSGVOLUME_BRICK 1 + +#include +#include + +#include + +#include + +namespace osgVolume { + +class Volume; + +class BrickID +{ + public: + + BrickID(): + level(-1), + x(-1), + y(-1) {} + + BrickID(int in_level, int in_x, int in_y): + level(in_level), + x(in_x), + y(in_y) {} + + bool operator == (const BrickID& rhs) const + { + return (level==rhs.level) && (x==rhs.x) && (y==rhs.y); + } + + bool operator != (const BrickID& rhs) const + { + return (level!=rhs.level) || (x!=rhs.x) || (y!=rhs.y); + } + + bool operator < (const BrickID& rhs) const + { + if (levelrhs.level) return false; + if (xrhs.x) return false; + return y=0; } + + int level; + int x; + int y; + int z; +}; + + +/** Terrain provides a framework for loosely coupling height field data with height rendering algorithms. + * This allows TerrainTechnique's to be plugged in at runtime.*/ +class OSGVOLUME_EXPORT Brick : public osg::Group +{ + public: + + Brick(); + + /** Copy constructor using CopyOp to manage deep vs shallow copy.*/ + Brick(const Brick&,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY); + + META_Node(osgVolume, Brick); + + virtual void traverse(osg::NodeVisitor& nv); + + /** Call init on any attached TerrainTechnique.*/ + void init(); + + + /** Set the Volume that this Volume tile is a member of.*/ + void setVolume(Volume* ts); + + /** Get the Volume that this Volume tile is a member of.*/ + Volume* getVolume() { return _volume; } + + /** Get the const Volume that this Volume tile is a member of.*/ + const Volume* getVolume() const { return _volume; } + + + /** Set the BrickID (layer, x,y) of the Brick. + * The BrickID is used so it can be located by its neighbours + * via the enclosing Terrain node that manages a map of BrickID to TerraiTiles.*/ + void setBrickID(const BrickID& brickID); + + /** Get the BrickID (layer, x,y) of the Brick.*/ + const BrickID& getBrickID() const { return _brickID; } + + + void setLocator(osg::RefMatrix* locator) { _locator = locator; } + osg::RefMatrix* getLocator() { return _locator.get(); } + const osg::RefMatrix* getLocator() const { return _locator.get(); } + + + void setImage(osg::Image* image) { _image = image; } + osg::Image* getImage() { return _image.get(); } + const osg::Image* getImage() const { return _image.get(); } + + + /** Set the VolumeTechnique*/ + void setVolumeTechnique(VolumeTechnique* VolumeTechnique); + + /** Get the VolumeTechnique*/ + VolumeTechnique* getVolumeTechnique() { return _volumeTechnique.get(); } + + /** Get the const VolumeTechnique*/ + const VolumeTechnique* getVolumeTechnique() const { return _volumeTechnique.get(); } + + + /** Set the dirty flag on/off.*/ + void setDirty(bool dirty); + + /** return true if the tile is dirty and needs to be updated,*/ + bool getDirty() const { return _dirty; } + + + virtual osg::BoundingSphere computeBound() const; + + protected: + + virtual ~Brick(); + + friend class Volume; + + Volume* _volume; + + bool _dirty; + bool _hasBeenTraversal; + + BrickID _brickID; + + osg::ref_ptr _volumeTechnique; + + osg::ref_ptr _locator; + osg::ref_ptr _image; +}; + +} + +#endif diff --git a/include/osgVolume/Volume b/include/osgVolume/Volume new file mode 100644 index 000000000..da96294c1 --- /dev/null +++ b/include/osgVolume/Volume @@ -0,0 +1,68 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2008 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * OpenSceneGraph Public License for more details. +*/ + +#ifndef OSGVOLUME +#define OSGVOLUME 1 + +#include +#include + +#include + +namespace osgVolume { + +/** Volume provides a framework for loosely coupling 3d image Brick's with volume algorithms. + * This allows VolumeTechnique's to be plugged in at runtime.*/ +class OSGVOLUME_EXPORT Volume : public osg::Group +{ + public: + + Volume(); + + /** Copy constructor using CopyOp to manage deep vs shallow copy.*/ + Volume(const Volume&,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY); + + META_Node(osgVolume, Volume); + + virtual void traverse(osg::NodeVisitor& nv); + + /** Get the Brick for a given BrickID.*/ + Brick* getBrick(const BrickID& brickID); + + /** Get the const Brick for a given BrickID.*/ + const Brick* getBrick(const BrickID& brickID) const; + + protected: + + virtual ~Volume(); + + friend class Brick; + + void dirtyRegisteredBricks(); + + void registerBrick(Brick* tile); + void unregisterBrick(Brick* tile); + + typedef std::map< BrickID, Brick* > BrickMap; + typedef std::set< Brick* > BrickSet; + + mutable OpenThreads::Mutex _mutex; + BrickSet _brickSet; + BrickMap _brickMap; + + +}; + +} + +#endif diff --git a/include/osgVolume/VolumeTechnique b/include/osgVolume/VolumeTechnique new file mode 100644 index 000000000..eb6594531 --- /dev/null +++ b/include/osgVolume/VolumeTechnique @@ -0,0 +1,68 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2008 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * OpenSceneGraph Public License for more details. +*/ + +#ifndef OSGVOLUME_VOLUMETECHNIQUE +#define OSGVOLUME_VOLUMETECHNIQUE 1 + +#include + +#include +#include + +#include + +namespace osgVolume { + +class Brick; + +class OSGVOLUME_EXPORT VolumeTechnique : public osg::Object +{ + public: + + VolumeTechnique(); + + /** Copy constructor using CopyOp to manage deep vs shallow copy.*/ + VolumeTechnique(const VolumeTechnique&,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY); + + META_Object(osgVolume, VolumeTechnique); + + Brick* getBrick() { return _brick; } + const Brick* getBrick() const { return _brick; } + + virtual void init(); + + virtual void update(osgUtil::UpdateVisitor* nv); + + virtual void cull(osgUtil::CullVisitor* nv); + + /** Clean scene graph from any terrain technique specific nodes.*/ + virtual void cleanSceneGraph(); + + /** Traverse the terrain subgraph.*/ + virtual void traverse(osg::NodeVisitor& nv); + + protected: + + void setDirty(bool dirty); + + virtual ~VolumeTechnique(); + + friend class osgVolume::Brick; + + Brick* _brick; + +}; + +} + +#endif diff --git a/src/osgVolume/Brick.cpp b/src/osgVolume/Brick.cpp new file mode 100644 index 000000000..5535d4fa6 --- /dev/null +++ b/src/osgVolume/Brick.cpp @@ -0,0 +1,166 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2008 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * OpenSceneGraph Public License for more details. +*/ + +#include +#include + + +using namespace osg; +using namespace osgVolume; + +///////////////////////////////////////////////////////////////////////////////// +// +// Brick +// +Brick::Brick(): + _volume(0), + _hasBeenTraversal(false), + _dirty(false) +{ + setThreadSafeRefUnref(true); +} + +Brick::Brick(const Brick& brick,const osg::CopyOp& copyop): + Group(brick,copyop), + _volume(0), + _hasBeenTraversal(false), + _image(brick._image), + _dirty(false) +{ + if (brick.getVolumeTechnique()) + { + setVolumeTechnique(osg::clone(brick.getVolumeTechnique())); + } +} + +Brick::~Brick() +{ + if (_volume) setVolume(0); +} + +void Brick::setVolume(Volume* volume) +{ + if (_volume == volume) return; + + if (_volume) _volume->unregisterBrick(this); + + _volume = volume; + + if (_volume) _volume->registerBrick(this); +} + +void Brick::setBrickID(const BrickID& brickID) +{ + if (_brickID == brickID) return; + + if (_volume) _volume->unregisterBrick(this); + + _brickID = brickID; + + if (_volume) _volume->registerBrick(this); +} + + +void Brick::traverse(osg::NodeVisitor& nv) +{ + if (!_hasBeenTraversal) + { + if (!_volume) + { + osg::NodePath& nodePath = nv.getNodePath(); + if (!nodePath.empty()) + { + for(osg::NodePath::reverse_iterator itr = nodePath.rbegin(); + itr != nodePath.rend() && !_volume; + ++itr) + { + osgVolume::Volume* volume = dynamic_cast(*itr); + if (volume) + { + osg::notify(osg::INFO)<<"Assigning volume system "<traverse(nv); + } + else + { + osg::Group::traverse(nv); + } +} + +void Brick::init() +{ + if (_volumeTechnique.valid() && getDirty()) + { + _volumeTechnique->init(); + + setDirty(false); + } +} + +void Brick::setVolumeTechnique(VolumeTechnique* volumeTechnique) +{ + if (_volumeTechnique == volumeTechnique) return; + + int dirtyDelta = _dirty ? -1 : 0; + + if (_volumeTechnique.valid()) + { + _volumeTechnique->_brick = 0; + } + + _volumeTechnique = volumeTechnique; + + if (_volumeTechnique.valid()) + { + _volumeTechnique->_brick = this; + ++dirtyDelta; + } + + if (dirtyDelta>0) setDirty(true); + else if (dirtyDelta<0) setDirty(false); +} + +void Brick::setDirty(bool dirty) +{ + if (_dirty==dirty) return; + + _dirty = dirty; + + if (_dirty) + { + setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()+1); + } + else if (getNumChildrenRequiringUpdateTraversal()>0) + { + setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()-1); + } +} + +osg::BoundingSphere Brick::computeBound() const +{ + osg::BoundingSphere bs; + + osg::notify(osg::NOTICE)<<"TODO Brick::computeBound()"< +#include + +using namespace osgVolume; + +Volume::Volume() +{ +} + +Volume::Volume(const Volume& ts, const osg::CopyOp& copyop): + osg::Group(ts,copyop) +{ +} + + +Volume::~Volume() +{ + OpenThreads::ScopedLock lock(_mutex); + + for(BrickSet::iterator itr = _brickSet.begin(); + itr != _brickSet.end(); + ++itr) + { + const_cast(*itr)->_volume = 0; + } + + _brickSet.clear(); + _brickMap.clear(); +} + +void Volume::traverse(osg::NodeVisitor& nv) +{ + Group::traverse(nv); +} + +Brick* Volume::getBrick(const BrickID& BrickID) +{ + OpenThreads::ScopedLock lock(_mutex); + + BrickMap::iterator itr = _brickMap.find(BrickID); + if (itr != _brickMap.end()) return 0; + + return itr->second; +} + +const Brick* Volume::getBrick(const BrickID& BrickID) const +{ + OpenThreads::ScopedLock lock(_mutex); + + BrickMap::const_iterator itr = _brickMap.find(BrickID); + if (itr != _brickMap.end()) return 0; + + return itr->second; +} + +void Volume::dirtyRegisteredBricks() +{ + OpenThreads::ScopedLock lock(_mutex); + + for(BrickSet::iterator itr = _brickSet.begin(); + itr != _brickSet.end(); + ++itr) + { + (const_cast(*itr))->setDirty(true); + } +} + +static unsigned int s_maxNumBricks = 0; +void Volume::registerBrick(Brick* Brick) +{ + if (!Brick) return; + + OpenThreads::ScopedLock lock(_mutex); + + if (Brick->getBrickID().valid()) + { + _brickMap[Brick->getBrickID()] = Brick; + } + + _brickSet.insert(Brick); + + if (_brickSet.size() > s_maxNumBricks) s_maxNumBricks = _brickSet.size(); + + // osg::notify(osg::NOTICE)<<"Volume::registerBrick "<osg::Group::traverse(*uv); +} + +void VolumeTechnique::cull(osgUtil::CullVisitor* cv) +{ + osg::notify(osg::NOTICE)<osg::Group::traverse(*cv); +} + +void VolumeTechnique::cleanSceneGraph() +{ + osg::notify(osg::NOTICE)<getDirty()) _brick->init(); + + osgUtil::UpdateVisitor* uv = dynamic_cast(&nv); + if (uv) + { + update(uv); + return; + } + + } + else if (nv.getVisitorType()==osg::NodeVisitor::CULL_VISITOR) + { + osgUtil::CullVisitor* cv = dynamic_cast(&nv); + if (cv) + { + cull(cv); + return; + } + } + + if (_brick->getDirty()) _brick->init(); + + // otherwise fallback to the Group::traverse() + _brick->osg::Group::traverse(nv); +}