diff --git a/examples/osgvolume/osgvolume.cpp b/examples/osgvolume/osgvolume.cpp index 192af181d..3f4231264 100644 --- a/examples/osgvolume/osgvolume.cpp +++ b/examples/osgvolume/osgvolume.cpp @@ -2309,6 +2309,23 @@ int main( int argc, char **argv ) if (useShader) { + switch(shadingModel) + { + case(Standard): + break; + case(Light): + layer->addProperty(new osgVolume::LightingProperty); + break; + case(Isosurface): + layer->addProperty(new osgVolume::IsoSurfaceProperty(alphaFunc)); + break; + case(MaximumIntensityProjection): + layer->addProperty(new osgVolume::MaximumIntensityProjectionProperty); + break; + } + + layer->addProperty(new osgVolume::AlphaFuncProperty(alphaFunc)); + tile->setVolumeTechnique(new osgVolume::ShaderTechnique); } else diff --git a/include/osgVolume/Layer b/include/osgVolume/Layer index d2099dbae..195f814ba 100644 --- a/include/osgVolume/Layer +++ b/include/osgVolume/Layer @@ -73,6 +73,9 @@ class OSGVOLUME_EXPORT Layer : public osg::Object /** Get the const Property that informs the VolumeTechnique how this layer should be rendered.*/ const Property* getProperty() const { return _property.get(); } + /** Add a property, automatically creating a CompositePorperty if one isn't already assigned.*/ + void addProperty(Property* property); + /** increment the modified count."*/ virtual void dirty() {}; diff --git a/include/osgVolume/Property b/include/osgVolume/Property index 47fdd306d..9d9d5a275 100644 --- a/include/osgVolume/Property +++ b/include/osgVolume/Property @@ -15,11 +15,39 @@ #define OSGVOLUME_PROPERTY 1 #include +#include #include namespace osgVolume { +// forward decarle +class Property; +class CompositeProperty; +class TransferFunctionProperty; +class ScalarProperty; +class IsoSurfaceProperty; +class MaximumIntensityProjectionProperty; +class LightingProperty; +class AlphaFuncProperty; + +class PropertyVisitor +{ + public: + + PropertyVisitor() {} + virtual ~PropertyVisitor() {} + + virtual void apply(Property&) {} + virtual void apply(CompositeProperty&) {} + virtual void apply(TransferFunctionProperty&) {} + virtual void apply(ScalarProperty&) {} + virtual void apply(IsoSurfaceProperty&) {} + virtual void apply(AlphaFuncProperty&) {} + virtual void apply(MaximumIntensityProjectionProperty&) {} + virtual void apply(LightingProperty&) {} +}; + class OSGVOLUME_EXPORT Property : public osg::Object { public: @@ -31,6 +59,8 @@ class OSGVOLUME_EXPORT Property : public osg::Object META_Object(osgVolume, Property); + virtual void accept(PropertyVisitor& pv) { pv.apply(*this); } + protected: virtual ~Property(); @@ -47,6 +77,8 @@ class OSGVOLUME_EXPORT CompositeProperty : public Property META_Object(osgVolume, CompositeProperty); + virtual void accept(PropertyVisitor& pv) { pv.apply(*this); } + void clear(); typedef std::vector< osg::ref_ptr > Properties; @@ -78,10 +110,21 @@ class OSGVOLUME_EXPORT TransferFunctionProperty : public Property TransferFunctionProperty(osg::TransferFunction* tf = 0); /** Copy constructor using CopyOp to manage deep vs shallow copy.*/ - TransferFunctionProperty(const TransferFunctionProperty& tfProperty,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY); + TransferFunctionProperty(const TransferFunctionProperty& tfp,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY); META_Object(osgVolume, TransferFunctionProperty); + virtual void accept(PropertyVisitor& pv) { pv.apply(*this); } + + /** Set the transfer function.*/ + void setTransferFunction(osg::TransferFunction* tf) { _tf = tf; } + + /** Get the transfer function.*/ + osg::TransferFunction* getTransferFunction() { return _tf.get(); } + + /** Get the const transfer function.*/ + const osg::TransferFunction* getTransferFunction() const { return _tf.get(); } + protected: virtual ~TransferFunctionProperty() {} @@ -90,6 +133,111 @@ class OSGVOLUME_EXPORT TransferFunctionProperty : public Property }; + +class OSGVOLUME_EXPORT ScalarProperty : public Property +{ + public: + + ScalarProperty(); + + ScalarProperty(const std::string& scaleName, float value); + + ScalarProperty(const ScalarProperty& scalarProperty,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY); + + META_Object(osgVolume, ScalarProperty); + + virtual void accept(PropertyVisitor& pv) { pv.apply(*this); } + + /** Set the value.*/ + void setValue(float v) { _uniform->set(v); } + + /** Get the value.*/ + float getValue() const { float v; _uniform->get(v); return v; } + + /** Get the underlying uniform.*/ + osg::Uniform* getUniform() { return _uniform.get(); } + + /** Get the underlying uniform.*/ + const osg::Uniform* getUniform() const { return _uniform.get(); } + + protected: + + virtual ~ScalarProperty() {} + + osg::ref_ptr _uniform; +}; + + +class OSGVOLUME_EXPORT IsoSurfaceProperty : public ScalarProperty +{ + public: + + IsoSurfaceProperty(float value=1.0); + + IsoSurfaceProperty(const IsoSurfaceProperty& isp,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY); + + META_Object(osgVolume, IsoSurfaceProperty); + + virtual void accept(PropertyVisitor& pv) { pv.apply(*this); } + + protected: + + virtual ~IsoSurfaceProperty() {} +}; + +class OSGVOLUME_EXPORT AlphaFuncProperty : public ScalarProperty +{ + public: + + AlphaFuncProperty(float value=1.0); + + AlphaFuncProperty(const AlphaFuncProperty& isp,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY); + + META_Object(osgVolume, AlphaFuncProperty); + + virtual void accept(PropertyVisitor& pv) { pv.apply(*this); } + + protected: + + virtual ~AlphaFuncProperty() {} +}; + +class OSGVOLUME_EXPORT MaximumIntensityProjectionProperty : public Property +{ + public: + + MaximumIntensityProjectionProperty(); + + MaximumIntensityProjectionProperty(const MaximumIntensityProjectionProperty& mipp,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY); + + META_Object(osgVolume, MaximumIntensityProjectionProperty); + + virtual void accept(PropertyVisitor& pv) { pv.apply(*this); } + + protected: + + virtual ~MaximumIntensityProjectionProperty() {} +}; + + +class OSGVOLUME_EXPORT LightingProperty : public Property +{ + public: + + LightingProperty(); + + LightingProperty(const LightingProperty& mipp,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY); + + META_Object(osgVolume, LightingProperty); + + virtual void accept(PropertyVisitor& pv) { pv.apply(*this); } + + protected: + + virtual ~LightingProperty() {} +}; + + } #endif diff --git a/include/osgVolume/VolumeTile b/include/osgVolume/VolumeTile index d756c1213..6b5e1052b 100644 --- a/include/osgVolume/VolumeTile +++ b/include/osgVolume/VolumeTile @@ -117,16 +117,17 @@ class OSGVOLUME_EXPORT VolumeTile : public osg::Group void setLayer(Layer* layer) { _layer = layer; } Layer* getLayer() { return _layer.get(); } - const Layer* getLayer() const { return _layer.get(); } + const Layer* getLayer() const { return _layer.get(); } - /** Set the VolumeTechnique*/ + + /** Set the VolumeTechnique that will be used to render this tile. */ void setVolumeTechnique(VolumeTechnique* VolumeTechnique); - /** Get the VolumeTechnique*/ + /** Get the VolumeTechnique that will be used to render this tile. */ VolumeTechnique* getVolumeTechnique() { return _volumeTechnique.get(); } - /** Get the const VolumeTechnique*/ + /** Get the const VolumeTechnique that will be used to render this tile. */ const VolumeTechnique* getVolumeTechnique() const { return _volumeTechnique.get(); } diff --git a/src/osgVolume/Layer.cpp b/src/osgVolume/Layer.cpp index 18c11e8e2..a52f3eac1 100644 --- a/src/osgVolume/Layer.cpp +++ b/src/osgVolume/Layer.cpp @@ -43,13 +43,36 @@ osg::BoundingSphere Layer::computeBound() const osg::Vec3d left, right; getLocator()->computeLocalBounds(left, right); - osg::notify(osg::NOTICE)<<"left = "<accept(*this); + } + } + virtual void apply(TransferFunctionProperty& tf) { _tfProperty = &tf; } + virtual void apply(ScalarProperty&) {} + virtual void apply(IsoSurfaceProperty& iso) { _isoProperty = &iso; } + virtual void apply(AlphaFuncProperty& af) { _afProperty = ⁡ } + virtual void apply(MaximumIntensityProjectionProperty& mip) { _mipProperty = &mip; } + virtual void apply(LightingProperty& lp) { _lightingProperty = &lp; } + + osg::ref_ptr _tfProperty; + osg::ref_ptr _isoProperty; + osg::ref_ptr _afProperty; + osg::ref_ptr _mipProperty; + osg::ref_ptr _lightingProperty; + +}; + void ShaderTechnique::init() { osg::notify(osg::NOTICE)<<"ShaderTechnique::init()"<getLayer()->getImage(); + CollectPropertiesVisitor cpv; + if (_volumeTile->getLayer()->getProperty()) + { + _volumeTile->getLayer()->getProperty()->accept(cpv); + } + + if (cpv._isoProperty.valid()) + { + shadingModel = Isosurface; + alphaFuncValue = cpv._isoProperty->getValue(); + } + else if (cpv._mipProperty.valid()) + { + shadingModel = MaximumIntensityProjection; + } + else if (cpv._lightingProperty.valid()) + { + shadingModel = Light; + } + else + { + shadingModel = Standard; + } + + if (cpv._tfProperty.valid()) + { + tf = dynamic_cast(cpv._tfProperty->getTransferFunction()); + } + + if (cpv._afProperty.valid()) + { + alphaFuncValue = cpv._afProperty->getValue(); + } + + if (_volumeTile->getLayer() && !masterLocator) { masterLocator = _volumeTile->getLayer()->getLocator(); diff --git a/src/osgVolume/VolumeTile.cpp b/src/osgVolume/VolumeTile.cpp index 51e16e663..363922a6d 100644 --- a/src/osgVolume/VolumeTile.cpp +++ b/src/osgVolume/VolumeTile.cpp @@ -158,7 +158,26 @@ void VolumeTile::setDirty(bool dirty) osg::BoundingSphere VolumeTile::computeBound() const { - if (_layer.valid()) return _layer->computeBound(); + const Locator* masterLocator = getLocator(); + if (_layer.valid() && !masterLocator) + { + masterLocator = _layer->getLocator(); + } - return osg::BoundingSphere(); + if (masterLocator) + { + osg::Vec3d left, right; + masterLocator->computeLocalBounds(left, right); + + return osg::BoundingSphere((left+right)*0.5, (right-left).length()*0.5); + } + else if (_layer.valid()) + { + // we have a layer but no Locator defined so will assume a Identity Locator + return osg::BoundingSphere( osg::Vec3(0.5,0.5,0.5), 0.867); + } + else + { + return osg::BoundingSphere(); + } }