You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
275 lines
10 KiB
275 lines
10 KiB
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2009 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_LAYER |
|
#define OSGVOLUME_LAYER 1 |
|
|
|
#include <osg/Image> |
|
#include <osg/TransferFunction> |
|
|
|
#include <osgVolume/Locator> |
|
#include <osgVolume/Property> |
|
|
|
namespace osgVolume { |
|
|
|
/** Data strucutre for passing details about the loading imagery on to osgVolume for use when setting up dimensions etc.*/ |
|
class OSGVOLUME_EXPORT ImageDetails : public osg::Object |
|
{ |
|
public: |
|
|
|
ImageDetails(); |
|
|
|
/** Copy constructor using CopyOp to manage deep vs shallow copy.*/ |
|
ImageDetails(const ImageDetails&,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY); |
|
|
|
META_Object(osgVolume, ImageDetails); |
|
|
|
void setTexelOffset(const osg::Vec4& offset) { _texelOffset = offset; } |
|
const osg::Vec4& getTexelOffset() const { return _texelOffset; } |
|
|
|
void setTexelScale(const osg::Vec4& scale) { _texelScale = scale; } |
|
const osg::Vec4& getTexelScale() const { return _texelScale; } |
|
|
|
void setMatrix(osg::RefMatrix* matrix) { _matrix = matrix; } |
|
osg::RefMatrix* getMatrix() { return _matrix.get(); } |
|
const osg::RefMatrix* getMatrix() const { return _matrix.get(); } |
|
|
|
protected: |
|
|
|
osg::Vec4 _texelOffset; |
|
osg::Vec4 _texelScale; |
|
osg::ref_ptr<osg::RefMatrix> _matrix; |
|
|
|
}; |
|
|
|
/** Base class for representing a single layer of volume data.*/ |
|
class OSGVOLUME_EXPORT Layer : public osg::Object |
|
{ |
|
public: |
|
|
|
Layer(); |
|
|
|
/** Copy constructor using CopyOp to manage deep vs shallow copy.*/ |
|
Layer(const Layer&,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY); |
|
|
|
META_Object(osgVolume, Layer); |
|
|
|
/** Set the file name of the data associated with this layer. */ |
|
virtual void setFileName(const std::string& filename) { _filename = filename; } |
|
|
|
/** Get the file name of the layer. */ |
|
virtual const std::string& getFileName() const { return _filename; } |
|
|
|
void setLocator(Locator* locator) { _locator = locator; } |
|
Locator* getLocator() { return _locator.get(); } |
|
const Locator* getLocator() const { return _locator.get(); } |
|
|
|
void setDefaultValue(const osg::Vec4& value) { _defaultValue = value; } |
|
const osg::Vec4& getDefaultValue() const { return _defaultValue; } |
|
|
|
/** Set the minification texture filter to use when do texture associated with this layer.*/ |
|
void setMinFilter(osg::Texture::FilterMode filter) { _minFilter = filter; } |
|
|
|
/** Get the minification texture filter to use when do texture associated with this layer.*/ |
|
osg::Texture::FilterMode getMinFilter() const { return _minFilter; } |
|
|
|
/** Set the magniification texture filter to use when do texture associated with this layer.*/ |
|
void setMagFilter(osg::Texture::FilterMode filter) { _magFilter = filter; } |
|
|
|
/** Get the magnification texture filter to use when do texture associated with this layer.*/ |
|
osg::Texture::FilterMode getMagFilter() const { return _magFilter; } |
|
|
|
/** Return image associated with layer if supported. */ |
|
virtual osg::Image* getImage() { return 0; } |
|
|
|
/** Return const image associated with layer if supported. */ |
|
virtual const osg::Image* getImage() const { return 0; } |
|
|
|
|
|
/** Set the Property (or Properties via the CompositeProperty) that informs the VolumeTechnique how this layer should be rendered.*/ |
|
void setProperty(Property* property) { _property = property; } |
|
|
|
/** Get the Property that informs the VolumeTechnique how this layer should be rendered.*/ |
|
Property* getProperty() { return _property.get(); } |
|
|
|
/** 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); |
|
|
|
|
|
/** Specify whether ImageLayer requires update traversal. */ |
|
virtual bool requiresUpdateTraversal() const { return false; } |
|
|
|
/** Call update on the Layer.*/ |
|
virtual void update(osg::NodeVisitor& /*nv*/) {} |
|
|
|
/** increment the modified count."*/ |
|
virtual void dirty() {}; |
|
|
|
/** Set the modified count value. */ |
|
virtual void setModifiedCount(unsigned int /*value*/) {}; |
|
|
|
/** Get modified count value. */ |
|
virtual unsigned int getModifiedCount() const { return 0; } |
|
|
|
virtual osg::BoundingSphere computeBound() const; |
|
|
|
protected: |
|
|
|
virtual ~Layer(); |
|
|
|
std::string _filename; |
|
osg::ref_ptr<Locator> _locator; |
|
osg::Vec4 _defaultValue; |
|
osg::Texture::FilterMode _minFilter; |
|
osg::Texture::FilterMode _magFilter; |
|
|
|
osg::ref_ptr<Property> _property; |
|
|
|
}; |
|
|
|
class OSGVOLUME_EXPORT ImageLayer : public Layer |
|
{ |
|
public: |
|
|
|
ImageLayer(osg::Image* image=0); |
|
|
|
/** Copy constructor using CopyOp to manage deep vs shallow copy.*/ |
|
ImageLayer(const ImageLayer& imageLayer,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY); |
|
|
|
META_Object(osgVolume, ImageLayer); |
|
|
|
void setFileName(const std::string& filename) { _filename = filename; if (_image.valid()) _image->setFileName(filename); } |
|
virtual const std::string& getFileName() const { return _image.get() ? _image->getFileName() : _filename; } |
|
|
|
void setImage(osg::Image* image); |
|
|
|
/** Return image associated with layer. */ |
|
virtual osg::Image* getImage() { return _image.get(); } |
|
|
|
/** Return const image associated with layer. */ |
|
virtual const osg::Image* getImage() const { return _image.get(); } |
|
|
|
|
|
void setTexelOffset(const osg::Vec4& offset) { _texelOffset = offset; } |
|
const osg::Vec4& getTexelOffset() const { return _texelOffset; } |
|
|
|
void setTexelScale(const osg::Vec4& scale) { _texelScale = scale; } |
|
const osg::Vec4& getTexelScale() const { return _texelScale; } |
|
|
|
|
|
/** Compute the min and max pixel colors.*/ |
|
bool computeMinMax(osg::Vec4& min, osg::Vec4& max); |
|
|
|
/** Apply color transformation to pixels using c' = offset + c * scale .*/ |
|
void offsetAndScaleImage(const osg::Vec4& offset, const osg::Vec4& scale); |
|
|
|
/** Compute the min max range of the image, and then remap this to a 0 to 1 range.*/ |
|
void rescaleToZeroToOneRange(); |
|
|
|
/** Compute the min color component of the image and then translate and pixels by this offset to make the new min component 0.*/ |
|
void translateMinToZero(); |
|
|
|
virtual bool requiresUpdateTraversal() const; |
|
|
|
virtual void update(osg::NodeVisitor& /*nv*/); |
|
|
|
virtual void dirty(); |
|
virtual void setModifiedCount(unsigned int value); |
|
virtual unsigned int getModifiedCount() const; |
|
|
|
protected: |
|
|
|
virtual ~ImageLayer() {} |
|
|
|
osg::Vec4 _texelOffset; |
|
osg::Vec4 _texelScale; |
|
osg::ref_ptr<osg::Image> _image; |
|
|
|
}; |
|
|
|
class OSGVOLUME_EXPORT CompositeLayer : public Layer |
|
{ |
|
public: |
|
|
|
CompositeLayer(); |
|
|
|
/** Copy constructor using CopyOp to manage deep vs shallow copy.*/ |
|
CompositeLayer(const CompositeLayer& compositeLayer,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY); |
|
|
|
META_Object(osgVolume, CompositeLayer); |
|
|
|
void clear(); |
|
|
|
void setFileName(unsigned int i, const std::string& filename) { if (i>=_layers.size()) _layers.resize(i+1); _layers[i].filename = filename; if (_layers[i].layer.valid()) _layers[i].layer->setFileName(filename); } |
|
const std::string& getFileName(unsigned int i) const { return _layers[i].layer.valid() ? _layers[i].layer->getFileName() : _layers[i].filename; } |
|
|
|
void setLayer(unsigned int i, Layer* layer) { if (i>=_layers.size()) _layers.resize(i+1); _layers[i].layer = layer; } |
|
Layer* getLayer(unsigned int i) { return i<_layers.size() ? _layers[i].layer.get() : 0; } |
|
const Layer* getLayer(unsigned int i) const { return i<_layers.size() ? _layers[i].layer.get() : 0; } |
|
|
|
void addLayer(Layer* layer) { _layers.push_back(NameLayer(layer->getFileName(),layer)); } |
|
|
|
void removeLayer(unsigned int i) { _layers.erase(_layers.begin()+i); } |
|
|
|
unsigned int getNumLayers() const { return _layers.size(); } |
|
|
|
bool requiresUpdateTraversal() const; |
|
|
|
virtual void update(osg::NodeVisitor& /*nv*/); |
|
|
|
protected: |
|
|
|
virtual ~CompositeLayer() {} |
|
|
|
struct NameLayer |
|
{ |
|
NameLayer() {} |
|
|
|
NameLayer(const NameLayer& cnl): |
|
filename(cnl.filename), |
|
layer(cnl.layer) {} |
|
|
|
NameLayer(const std::string& fn, Layer* l): |
|
filename(fn), |
|
layer(l) {} |
|
|
|
NameLayer& operator = (const NameLayer& cnl) |
|
{ |
|
if (&cnl==this) return *this; |
|
|
|
filename = cnl.filename; |
|
layer = cnl.layer; |
|
return *this; |
|
} |
|
|
|
std::string filename; |
|
osg::ref_ptr<Layer> layer; |
|
}; |
|
|
|
typedef std::vector< NameLayer > Layers; |
|
|
|
Layers _layers; |
|
}; |
|
|
|
/** Compute a 3d image that represent the normal map of the specified 3d image.*/ |
|
extern OSGVOLUME_EXPORT osg::Image* createNormalMapTexture(osg::Image* image_3d); |
|
|
|
/** Create an image that has a transfer function applied specified Image.*/ |
|
extern OSGVOLUME_EXPORT osg::Image* applyTransferFunction(osg::Image* image, osg::TransferFunction1D* transferFunction); |
|
|
|
} |
|
|
|
#endif
|
|
|