diff --git a/examples/osgvolume/CMakeLists.txt b/examples/osgvolume/CMakeLists.txt index 2a5dd8121..4b74bbbd2 100644 --- a/examples/osgvolume/CMakeLists.txt +++ b/examples/osgvolume/CMakeLists.txt @@ -1,6 +1,6 @@ -#this file is automatically generated - - SET(TARGET_SRC osgvolume.cpp ) + +SET(TARGET_ADDED_LIBRARIES osgVolume ) + #### end var setup ### SETUP_EXAMPLE(osgvolume) diff --git a/examples/osgvolume/osgvolume.cpp b/examples/osgvolume/osgvolume.cpp index 3c3e7bd47..c3c732b54 100644 --- a/examples/osgvolume/osgvolume.cpp +++ b/examples/osgvolume/osgvolume.cpp @@ -54,6 +54,7 @@ #include #include +#include typedef std::vector< osg::ref_ptr > ImageList; @@ -68,105 +69,6 @@ typedef std::vector< osg::ref_ptr > ImageList; // }; -template -void _readRow(unsigned int num, GLenum pixelFormat, T* data,float scale, const O& operation) -{ - switch(pixelFormat) - { - case(GL_LUMINANCE): { for(unsigned int i=0;i -void readRow(unsigned int num, GLenum pixelFormat, GLenum dataType, unsigned char* data, const O& operation) -{ - switch(dataType) - { - case(GL_BYTE): _readRow(num,pixelFormat, (char*)data, 1.0f/128.0f, operation); break; - case(GL_UNSIGNED_BYTE): _readRow(num,pixelFormat, (unsigned char*)data, 1.0f/255.0f, operation); break; - case(GL_SHORT): _readRow(num,pixelFormat, (short*) data, 1.0f/32768.0f, operation); break; - case(GL_UNSIGNED_SHORT): _readRow(num,pixelFormat, (unsigned short*)data, 1.0f/65535.0f, operation); break; - case(GL_INT): _readRow(num,pixelFormat, (int*) data, 1.0f/2147483648.0f, operation); break; - case(GL_UNSIGNED_INT): _readRow(num,pixelFormat, (unsigned int*) data, 1.0f/4294967295.0f, operation); break; - case(GL_FLOAT): _readRow(num,pixelFormat, (float*) data, 1.0f, operation); break; - } -} - -template -void readImage(osg::Image* image, const O& operation) -{ - if (!image) return; - - for(int r=0;rr();++r) - { - for(int t=0;tt();++t) - { - readRow(image->s(), image->getPixelFormat(), image->getDataType(), image->data(0,t,r), operation); - } - } -} - -// example ModifyOperator -// struct ModifyOperator -// { -// inline void luminance(float& l) const {} -// inline void alpha(float& a) const {} -// inline void luminance_alpha(float& l,float& a) const {} -// inline void rgb(float& r,float& g,float& b) const {} -// inline void rgba(float& r,float& g,float& b,float& a) const {} -// }; - - -template -void _modifyRow(unsigned int num, GLenum pixelFormat, T* data,float scale, const M& operation) -{ - float inv_scale = 1.0f/scale; - switch(pixelFormat) - { - case(GL_LUMINANCE): { for(unsigned int i=0;i -void modifyRow(unsigned int num, GLenum pixelFormat, GLenum dataType, unsigned char* data, const M& operation) -{ - switch(dataType) - { - case(GL_BYTE): _modifyRow(num,pixelFormat, (char*)data, 1.0f/128.0f, operation); break; - case(GL_UNSIGNED_BYTE): _modifyRow(num,pixelFormat, (unsigned char*)data, 1.0f/255.0f, operation); break; - case(GL_SHORT): _modifyRow(num,pixelFormat, (short*) data, 1.0f/32768.0f, operation); break; - case(GL_UNSIGNED_SHORT): _modifyRow(num,pixelFormat, (unsigned short*)data, 1.0f/65535.0f, operation); break; - case(GL_INT): _modifyRow(num,pixelFormat, (int*) data, 1.0f/2147483648.0f, operation); break; - case(GL_UNSIGNED_INT): _modifyRow(num,pixelFormat, (unsigned int*) data, 1.0f/4294967295.0f, operation); break; - case(GL_FLOAT): _modifyRow(num,pixelFormat, (float*) data, 1.0f, operation); break; - } -} - -template -void modifyImage(osg::Image* image, const M& operation) -{ - if (!image) return; - - for(int r=0;rr();++r) - { - for(int t=0;tt();++t) - { - modifyRow(image->s(), image->getPixelFormat(), image->getDataType(), image->data(0,t,r), operation); - } - } -} struct PassThroughTransformFunction { @@ -934,7 +836,7 @@ osg::Node* createShaderModel(osg::ref_ptr& image_3d, osg::ref_ptrmax_iteratrions) \n" " {\n" @@ -1304,27 +1206,6 @@ osg::Node* createModel(osg::ref_ptr& image_3d, return group; } -struct FindRangeOperator -{ - FindRangeOperator(): - _rmin(FLT_MAX), - _rmax(-FLT_MAX), - _gmin(FLT_MAX), - _gmax(-FLT_MAX), - _bmin(FLT_MAX), - _bmax(-FLT_MAX), - _amin(FLT_MAX), - _amax(-FLT_MAX) {} - - mutable float _rmin, _rmax, _gmin, _gmax, _bmin, _bmax, _amin, _amax; - - inline void luminance(float l) const { rgb(l,l,l); } - inline void alpha(float a) const { _amin = osg::minimum(a,_amin); _amax = osg::maximum(a,_amax); } - inline void luminance_alpha(float l,float a) const { rgb(l,l,l); alpha(a); } - inline void rgb(float r,float g,float b) const { _rmin = osg::minimum(r,_rmin); _rmax = osg::maximum(r,_rmax); _gmin = osg::minimum(g,_gmin); _gmax = osg::maximum(g,_gmax); _bmin = osg::minimum(b,_bmin); _bmax = osg::maximum(b,_bmax); } - inline void rgba(float r,float g,float b,float a) const { rgb(r,g,b); alpha(a); } -}; - struct ScaleOperator { ScaleOperator():_scale(1.0f) {} @@ -1444,9 +1325,9 @@ osg::Image* readRaw(int sizeX, int sizeY, int sizeZ, int numberBytesPerComponent // normalise texture { // compute range of values - FindRangeOperator rangeOp; - readImage(image.get(), rangeOp); - modifyImage(image.get(),ScaleOperator(1.0f/rangeOp._rmax)); + osg::Vec4 minValue, maxValue; + osgVolume::computeMinMax(image.get(), minValue, maxValue); + osgVolume::modifyImage(image.get(),ScaleOperator(1.0f/maxValue.r())); } @@ -1471,12 +1352,12 @@ osg::Image* readRaw(int sizeX, int sizeY, int sizeZ, int numberBytesPerComponent writeOp._pos = 0; // read the pixels into readOp's _colour array - readRow(sizeS, pixelFormat, dataType, image->data(0,t,r), readOp); + osgVolume::readRow(sizeS, pixelFormat, dataType, image->data(0,t,r), readOp); // pass readOp's _colour array contents over to writeOp (note this is just a pointer swap). writeOp._colours.swap(readOp._colours); - modifyRow(sizeS, pixelFormat, GL_UNSIGNED_BYTE, new_image->data(0,t,r), writeOp); + osgVolume::modifyRow(sizeS, pixelFormat, GL_UNSIGNED_BYTE, new_image->data(0,t,r), writeOp); // return readOp's _colour array contents back to its rightful owner. writeOp._colours.swap(readOp._colours); @@ -1541,15 +1422,15 @@ void doColourSpaceConversion(ColourSpaceOperation op, osg::Image* image, osg::Ve { case (MODULATE_ALPHA_BY_LUMINANCE): std::cout<<"doing conversion MODULATE_ALPHA_BY_LUMINANCE"<allocateImage(image->s(),image->t(), image->r(), GL_RGBA, GL_UNSIGNED_BYTE); - readImage(image,ApplyTransferFunctionOperator(transferFunction, output_image->data())); + ApplyTransferFunctionOperator op(transferFunction, output_image->data()); + osgVolume::readImage(image,op); return output_image; } @@ -1912,6 +1794,51 @@ int main( int argc, char **argv ) std::cout<<"No model loaded, please specify and volumetric image file on the command line."<(image_3d->getUserData()); + if (matrix) + { + osg::notify(osg::NOTICE)<<"Image has Matrix = "<<*matrix<s() * (*matrix)(0,0); + ySize = image_3d->t() * (*matrix)(1,1); + zSize = image_3d->r() * (*matrix)(2,2); + } + + + osg::Vec4 minValue, maxValue; + if (osgVolume::computeMinMax(image_3d.get(), minValue, maxValue)); + { + osg::notify(osg::NOTICE)<<"Min value "< normalmap_3d = createNormalMap ? createNormalMapTexture(image_3d.get()) : 0; - osg::RefMatrix* matrix = dynamic_cast(image_3d->getUserData()); - if (matrix) - { - osg::notify(osg::NOTICE)<<"Image has Matrix = "<<*matrix<s() * (*matrix)(0,0); - ySize = image_3d->t() * (*matrix)(1,1); - zSize = image_3d->r() * (*matrix)(2,2); - } - - + // create a model from the images. osg::Node* rootNode = 0; diff --git a/include/osgVolume/Export b/include/osgVolume/Export new file mode 100644 index 000000000..3493e2740 --- /dev/null +++ b/include/osgVolume/Export @@ -0,0 +1,47 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 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_EXPORT_ +#define OSGVOLUME_EXPORT_ 1 + +#if defined(_MSC_VER) + #pragma warning( disable : 4244 ) + #pragma warning( disable : 4251 ) + #pragma warning( disable : 4267 ) + #pragma warning( disable : 4275 ) + #pragma warning( disable : 4290 ) + #pragma warning( disable : 4786 ) + #pragma warning( disable : 4305 ) + #pragma warning( disable : 4996 ) +#endif + +#if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__) || defined( __BCPLUSPLUS__) + # if defined( OSG_LIBRARY_STATIC ) + # define OSGVOLUME_EXPORT + # elif defined( OSGVOLUME_LIBRARY ) + # define OSGVOLUME_EXPORT __declspec(dllexport) + # else + # define OSGVOLUME_EXPORT __declspec(dllimport) + # endif +#else + # define OSGVOLUME_EXPORT +#endif + +/** + +\namespace osgVolume + +The osgVolume library is a NodeKit that extends the core scene graph to support volume rendering. +*/ + +#endif diff --git a/include/osgVolume/ImageUtils b/include/osgVolume/ImageUtils new file mode 100644 index 000000000..5468fdec9 --- /dev/null +++ b/include/osgVolume/ImageUtils @@ -0,0 +1,132 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 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_IMAGEUTILS +#define OSGVOLUME_IMAGEUTILS 1 + +#include + +#include + +namespace osgVolume { + +template +void _readRow(unsigned int num, GLenum pixelFormat, const T* data,float scale, O& operation) +{ + switch(pixelFormat) + { + case(GL_LUMINANCE): { for(unsigned int i=0;i +void readRow(unsigned int num, GLenum pixelFormat, GLenum dataType, const unsigned char* data, O& operation) +{ + switch(dataType) + { + case(GL_BYTE): _readRow(num,pixelFormat, (const char*)data, 1.0f/128.0f, operation); break; + case(GL_UNSIGNED_BYTE): _readRow(num,pixelFormat, (const unsigned char*)data, 1.0f/255.0f, operation); break; + case(GL_SHORT): _readRow(num,pixelFormat, (const short*) data, 1.0f/32768.0f, operation); break; + case(GL_UNSIGNED_SHORT): _readRow(num,pixelFormat, (const unsigned short*)data, 1.0f/65535.0f, operation); break; + case(GL_INT): _readRow(num,pixelFormat, (const int*) data, 1.0f/2147483648.0f, operation); break; + case(GL_UNSIGNED_INT): _readRow(num,pixelFormat, (const unsigned int*) data, 1.0f/4294967295.0f, operation); break; + case(GL_FLOAT): _readRow(num,pixelFormat, (const float*) data, 1.0f, operation); break; + } +} + +template +void readImage(const osg::Image* image, O& operation) +{ + if (!image) return; + + for(int r=0;rr();++r) + { + for(int t=0;tt();++t) + { + readRow(image->s(), image->getPixelFormat(), image->getDataType(), image->data(0,t,r), operation); + } + } +} + +// example ModifyOperator +// struct ModifyOperator +// { +// inline void luminance(float& l) const {} +// inline void alpha(float& a) const {} +// inline void luminance_alpha(float& l,float& a) const {} +// inline void rgb(float& r,float& g,float& b) const {} +// inline void rgba(float& r,float& g,float& b,float& a) const {} +// }; + + +template +void _modifyRow(unsigned int num, GLenum pixelFormat, T* data,float scale, const M& operation) +{ + float inv_scale = 1.0f/scale; + switch(pixelFormat) + { + case(GL_LUMINANCE): { for(unsigned int i=0;i +void modifyRow(unsigned int num, GLenum pixelFormat, GLenum dataType, unsigned char* data, const M& operation) +{ + switch(dataType) + { + case(GL_BYTE): _modifyRow(num,pixelFormat, (char*)data, 1.0f/128.0f, operation); break; + case(GL_UNSIGNED_BYTE): _modifyRow(num,pixelFormat, (unsigned char*)data, 1.0f/255.0f, operation); break; + case(GL_SHORT): _modifyRow(num,pixelFormat, (short*) data, 1.0f/32768.0f, operation); break; + case(GL_UNSIGNED_SHORT): _modifyRow(num,pixelFormat, (unsigned short*)data, 1.0f/65535.0f, operation); break; + case(GL_INT): _modifyRow(num,pixelFormat, (int*) data, 1.0f/2147483648.0f, operation); break; + case(GL_UNSIGNED_INT): _modifyRow(num,pixelFormat, (unsigned int*) data, 1.0f/4294967295.0f, operation); break; + case(GL_FLOAT): _modifyRow(num,pixelFormat, (float*) data, 1.0f, operation); break; + } +} + +template +void modifyImage(osg::Image* image, const M& operation) +{ + if (!image) return; + + for(int r=0;rr();++r) + { + for(int t=0;tt();++t) + { + modifyRow(image->s(), image->getPixelFormat(), image->getDataType(), image->data(0,t,r), operation); + } + } +} + +/** Compute the min max colour values in the image.*/ +extern OSGVOLUME_EXPORT bool computeMinMax(const osg::Image* image, osg::Vec4& min, osg::Vec4& max); + +/** Compute the min max colour values in the image.*/ +extern OSGVOLUME_EXPORT bool offsetAndScaleImage(osg::Image* image, const osg::Vec4& offset, const osg::Vec4& scale); + +} + + +#endif diff --git a/include/osgVolume/Version b/include/osgVolume/Version new file mode 100644 index 000000000..17b194397 --- /dev/null +++ b/include/osgVolume/Version @@ -0,0 +1,46 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 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_VERSION +#define OSGVOLUME_VERSION 1 + +#include + +extern "C" { + +/** + * osgVolumeGetVersion() returns the library version number. + * Numbering convention : OpenSceneGraph-1.0 will return 1.0 from osgVolumeGetVersion. + * + * This C function can be also used to check for the existence of the OpenSceneGraph + * library using autoconf and its m4 macro AC_CHECK_LIB. + * + * Here is the code to add to your configure.in: + \verbatim + # + # Check for the OpenSceneGraph (OSG) Volume library + # + AC_CHECK_LIB(osg, osgVolumeGetVersion, , + [AC_MSG_ERROR(OpenSceneGraph Volume library not found. See http://www.openscenegraph.org)],) + \endverbatim +*/ +extern OSGVOLUME_EXPORT const char* osgVolumeGetVersion(); + +/** + * osgVolumeGetLibraryName() returns the library name in human friendly form. +*/ +extern OSGVOLUME_EXPORT const char* osgVolumeGetLibraryName(); + +} + +#endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 711165b8b..2d3ffb9a8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -12,6 +12,7 @@ FOREACH( mylibfolder osgParticle osgShadow osgTerrain + osgVolume osgViewer ) diff --git a/src/osgVolume/CMakeLists.txt b/src/osgVolume/CMakeLists.txt new file mode 100644 index 000000000..147a6324b --- /dev/null +++ b/src/osgVolume/CMakeLists.txt @@ -0,0 +1,33 @@ + +IF (DYNAMIC_OPENSCENEGRAPH) + ADD_DEFINITIONS(-DOSGVOLUME_LIBRARY) +ELSE (DYNAMIC_OPENSCENEGRAPH) + ADD_DEFINITIONS(-DOSG_LIBRARY_STATIC) +ENDIF(DYNAMIC_OPENSCENEGRAPH) + +SET(LIB_NAME osgVolume) +SET(HEADER_PATH ${OpenSceneGraph_SOURCE_DIR}/include/${LIB_NAME}) +SET(LIB_PUBLIC_HEADERS + ${HEADER_PATH}/Export + ${HEADER_PATH}/ImageUtils + ${HEADER_PATH}/Version +) + +# FIXME: For OS X, need flag for Framework or dylib +ADD_LIBRARY(${LIB_NAME} + ${OPENSCENEGRAPH_USER_DEFINED_DYNAMIC_OR_STATIC} + ${LIB_PUBLIC_HEADERS} + ImageUtils.cpp + Version.cpp +) + + +SET(TARGET_LIBRARIES_VARS FREETYPE_LIBRARY ) +LINK_INTERNAL(${LIB_NAME} + osgDB + osg + OpenThreads +) +LINK_CORELIB_DEFAULT(${LIB_NAME}) + +INCLUDE(ModuleInstall OPTIONAL) diff --git a/src/osgVolume/ImageUtils.cpp b/src/osgVolume/ImageUtils.cpp new file mode 100644 index 000000000..81f1ce4b2 --- /dev/null +++ b/src/osgVolume/ImageUtils.cpp @@ -0,0 +1,123 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 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 +#include +#include + +using namespace osgVolume; + +namespace osgVolume +{ + +struct FindRangeOperator +{ + FindRangeOperator(): + _rmin(FLT_MAX), + _rmax(-FLT_MAX), + _gmin(FLT_MAX), + _gmax(-FLT_MAX), + _bmin(FLT_MAX), + _bmax(-FLT_MAX), + _amin(FLT_MAX), + _amax(-FLT_MAX) {} + + float _rmin, _rmax, _gmin, _gmax, _bmin, _bmax, _amin, _amax; + + inline void luminance(float l) { rgba(l,l,l,l); } + inline void alpha(float a) { rgba(1.0f,1.0f,1.0f,a); } + inline void luminance_alpha(float l,float a) { rgba(l,l,l,a); } + inline void rgb(float r,float g,float b) { rgba(r,g,b,1.0f); } + inline void rgba(float r,float g,float b,float a) + { + _rmin = osg::minimum(r,_rmin); + _rmax = osg::maximum(r,_rmax); + _gmin = osg::minimum(g,_gmin); + _gmax = osg::maximum(g,_gmax); + _bmin = osg::minimum(b,_bmin); + _bmax = osg::maximum(b,_bmax); + _amin = osg::minimum(a,_amin); + _amax = osg::maximum(a,_amax); + } + + + +}; + +struct OffsetAndScaleOperator +{ + OffsetAndScaleOperator(const osg::Vec4& offset, const osg::Vec4& scale): + _offset(offset), + _scale(scale) {} + + osg::Vec4 _offset; + osg::Vec4 _scale; + + inline void luminance(float& l) const { l= _offset.r() + l*_scale.r(); } + inline void alpha(float& a) const { a = _offset.a() + a*_scale.a(); } + inline void luminance_alpha(float& l,float& a) const + { + l= _offset.r() + l*_scale.r(); + a = _offset.a() + a*_scale.a(); + } + inline void rgb(float& r,float& g,float& b) const + { + r = _offset.r() + r*_scale.r(); + g = _offset.g() + g*_scale.g(); + b = _offset.b() + b*_scale.b(); + } + inline void rgba(float& r,float& g,float& b,float& a) const + { + r = _offset.r() + r*_scale.r(); + g = _offset.g() + g*_scale.g(); + b = _offset.b() + b*_scale.b(); + a = _offset.a() + a*_scale.a(); + } +}; + +} + +bool osgVolume::computeMinMax(const osg::Image* image, osg::Vec4& minValue, osg::Vec4& maxValue) +{ + if (!image) return false; + + osgVolume::FindRangeOperator rangeOp; + readImage(image, rangeOp); + minValue.r() = rangeOp._rmin; + minValue.g() = rangeOp._gmin; + minValue.b() = rangeOp._bmin; + minValue.a() = rangeOp._amin; + + maxValue.r() = rangeOp._rmax; + maxValue.g() = rangeOp._gmax; + maxValue.b() = rangeOp._bmax; + maxValue.a() = rangeOp._amax; + + return minValue.r()<=maxValue.r() && + minValue.g()<=maxValue.g() && + minValue.b()<=maxValue.b() && + minValue.a()<=maxValue.a(); +} + +bool osgVolume::offsetAndScaleImage(osg::Image* image, const osg::Vec4& offset, const osg::Vec4& scale) +{ + if (!image) return false; + + osgVolume::modifyImage(image,osgVolume::OffsetAndScaleOperator(offset, scale)); + + return true; +} + + + diff --git a/src/osgVolume/Version.cpp b/src/osgVolume/Version.cpp new file mode 100644 index 000000000..790f2f174 --- /dev/null +++ b/src/osgVolume/Version.cpp @@ -0,0 +1,30 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 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 + +extern "C" { + +const char* osgVolumeGetVersion() +{ + return osgGetVersion(); +} + + +const char* osgVolumeGetLibraryName() +{ + return "OpenSceneGraph Volume Library"; +} + +}