Introduced beginings of osgVolume NodeKit.
This commit is contained in:
parent
28af7882f5
commit
6ea2adf1f5
@ -1,6 +1,6 @@
|
|||||||
#this file is automatically generated
|
|
||||||
|
|
||||||
|
|
||||||
SET(TARGET_SRC osgvolume.cpp )
|
SET(TARGET_SRC osgvolume.cpp )
|
||||||
|
|
||||||
|
SET(TARGET_ADDED_LIBRARIES osgVolume )
|
||||||
|
|
||||||
#### end var setup ###
|
#### end var setup ###
|
||||||
SETUP_EXAMPLE(osgvolume)
|
SETUP_EXAMPLE(osgvolume)
|
||||||
|
@ -54,6 +54,7 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <osgVolume/ImageUtils>
|
||||||
|
|
||||||
typedef std::vector< osg::ref_ptr<osg::Image> > ImageList;
|
typedef std::vector< osg::ref_ptr<osg::Image> > ImageList;
|
||||||
|
|
||||||
@ -68,105 +69,6 @@ typedef std::vector< osg::ref_ptr<osg::Image> > ImageList;
|
|||||||
// };
|
// };
|
||||||
|
|
||||||
|
|
||||||
template <typename T, class O>
|
|
||||||
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<num;++i) { float l = float(*data++)*scale; operation.luminance(l); } } break;
|
|
||||||
case(GL_ALPHA): { for(unsigned int i=0;i<num;++i) { float a = float(*data++)*scale; operation.alpha(a); } } break;
|
|
||||||
case(GL_LUMINANCE_ALPHA): { for(unsigned int i=0;i<num;++i) { float l = float(*data++)*scale; float a = float(*data++)*scale; operation.luminance_alpha(l,a); } } break;
|
|
||||||
case(GL_RGB): { for(unsigned int i=0;i<num;++i) { float r = float(*data++)*scale; float g = float(*data++)*scale; float b = float(*data++)*scale; operation.rgb(r,g,b); } } break;
|
|
||||||
case(GL_RGBA): { for(unsigned int i=0;i<num;++i) { float r = float(*data++)*scale; float g = float(*data++)*scale; float b = float(*data++)*scale; float a = float(*data++)*scale; operation.rgba(r,g,b,a); } } break;
|
|
||||||
case(GL_BGR): { for(unsigned int i=0;i<num;++i) { float b = float(*data++)*scale; float g = float(*data++)*scale; float r = float(*data++)*scale; operation.rgb(r,g,b); } } break;
|
|
||||||
case(GL_BGRA): { for(unsigned int i=0;i<num;++i) { float b = float(*data++)*scale; float g = float(*data++)*scale; float r = float(*data++)*scale; float a = float(*data++)*scale; operation.rgba(r,g,b,a); } } break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class O>
|
|
||||||
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 <class O>
|
|
||||||
void readImage(osg::Image* image, const O& operation)
|
|
||||||
{
|
|
||||||
if (!image) return;
|
|
||||||
|
|
||||||
for(int r=0;r<image->r();++r)
|
|
||||||
{
|
|
||||||
for(int t=0;t<image->t();++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 <typename T, class M>
|
|
||||||
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<num;++i) { float l = float(*data)*scale; operation.luminance(l); *data++ = T(l*inv_scale); } } break;
|
|
||||||
case(GL_ALPHA): { for(unsigned int i=0;i<num;++i) { float a = float(*data)*scale; operation.alpha(a); *data++ = T(a*inv_scale); } } break;
|
|
||||||
case(GL_LUMINANCE_ALPHA): { for(unsigned int i=0;i<num;++i) { float l = float(*data)*scale; float a = float(*(data+1))*scale; operation.luminance_alpha(l,a); *data++ = T(l*inv_scale); *data++ = T(a*inv_scale); } } break;
|
|
||||||
case(GL_RGB): { for(unsigned int i=0;i<num;++i) { float r = float(*data)*scale; float g = float(*(data+1))*scale; float b = float(*(data+2))*scale; operation.rgb(r,g,b); *data++ = T(r*inv_scale); *data++ = T(g*inv_scale); *data++ = T(b*inv_scale); } } break;
|
|
||||||
case(GL_RGBA): { for(unsigned int i=0;i<num;++i) { float r = float(*data)*scale; float g = float(*(data+1))*scale; float b = float(*(data+2))*scale; float a = float(*(data+3))*scale; operation.rgba(r,g,b,a); *data++ = T(r*inv_scale); *data++ = T(g*inv_scale); *data++ = T(g*inv_scale); *data++ = T(a*inv_scale); } } break;
|
|
||||||
case(GL_BGR): { for(unsigned int i=0;i<num;++i) { float b = float(*data)*scale; float g = float(*(data+1))*scale; float r = float(*(data+2))*scale; operation.rgb(r,g,b); *data++ = T(b*inv_scale); *data++ = T(g*inv_scale); *data++ = T(r*inv_scale); } } break;
|
|
||||||
case(GL_BGRA): { for(unsigned int i=0;i<num;++i) { float b = float(*data)*scale; float g = float(*(data+1))*scale; float r = float(*(data+2))*scale; float a = float(*(data+3))*scale; operation.rgba(r,g,b,a); *data++ = T(g*inv_scale); *data++ = T(b*inv_scale); *data++ = T(r*inv_scale); *data++ = T(a*inv_scale); } } break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class M>
|
|
||||||
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 <class M>
|
|
||||||
void modifyImage(osg::Image* image, const M& operation)
|
|
||||||
{
|
|
||||||
if (!image) return;
|
|
||||||
|
|
||||||
for(int r=0;r<image->r();++r)
|
|
||||||
{
|
|
||||||
for(int t=0;t<image->t();++t)
|
|
||||||
{
|
|
||||||
modifyRow(image->s(), image->getPixelFormat(), image->getDataType(), image->data(0,t,r), operation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct PassThroughTransformFunction
|
struct PassThroughTransformFunction
|
||||||
{
|
{
|
||||||
@ -934,7 +836,7 @@ osg::Node* createShaderModel(osg::ref_ptr<osg::Image>& image_3d, osg::ref_ptr<os
|
|||||||
" }\n"
|
" }\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"\n"
|
"\n"
|
||||||
" const float max_iteratrions = 256.0;\n"
|
" const float max_iteratrions = 2048.0;\n"
|
||||||
" float num_iterations = length(te-t0)/sampleDensity;\n"
|
" float num_iterations = length(te-t0)/sampleDensity;\n"
|
||||||
" if (num_iterations>max_iteratrions) \n"
|
" if (num_iterations>max_iteratrions) \n"
|
||||||
" {\n"
|
" {\n"
|
||||||
@ -1304,27 +1206,6 @@ osg::Node* createModel(osg::ref_ptr<osg::Image>& image_3d,
|
|||||||
return group;
|
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
|
struct ScaleOperator
|
||||||
{
|
{
|
||||||
ScaleOperator():_scale(1.0f) {}
|
ScaleOperator():_scale(1.0f) {}
|
||||||
@ -1444,9 +1325,9 @@ osg::Image* readRaw(int sizeX, int sizeY, int sizeZ, int numberBytesPerComponent
|
|||||||
// normalise texture
|
// normalise texture
|
||||||
{
|
{
|
||||||
// compute range of values
|
// compute range of values
|
||||||
FindRangeOperator rangeOp;
|
osg::Vec4 minValue, maxValue;
|
||||||
readImage(image.get(), rangeOp);
|
osgVolume::computeMinMax(image.get(), minValue, maxValue);
|
||||||
modifyImage(image.get(),ScaleOperator(1.0f/rangeOp._rmax));
|
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;
|
writeOp._pos = 0;
|
||||||
|
|
||||||
// read the pixels into readOp's _colour array
|
// 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).
|
// pass readOp's _colour array contents over to writeOp (note this is just a pointer swap).
|
||||||
writeOp._colours.swap(readOp._colours);
|
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.
|
// return readOp's _colour array contents back to its rightful owner.
|
||||||
writeOp._colours.swap(readOp._colours);
|
writeOp._colours.swap(readOp._colours);
|
||||||
@ -1541,15 +1422,15 @@ void doColourSpaceConversion(ColourSpaceOperation op, osg::Image* image, osg::Ve
|
|||||||
{
|
{
|
||||||
case (MODULATE_ALPHA_BY_LUMINANCE):
|
case (MODULATE_ALPHA_BY_LUMINANCE):
|
||||||
std::cout<<"doing conversion MODULATE_ALPHA_BY_LUMINANCE"<<std::endl;
|
std::cout<<"doing conversion MODULATE_ALPHA_BY_LUMINANCE"<<std::endl;
|
||||||
modifyImage(image,ModulateAlphaByLuminanceOperator());
|
osgVolume::modifyImage(image,ModulateAlphaByLuminanceOperator());
|
||||||
break;
|
break;
|
||||||
case (MODULATE_ALPHA_BY_COLOUR):
|
case (MODULATE_ALPHA_BY_COLOUR):
|
||||||
std::cout<<"doing conversion MODULATE_ALPHA_BY_COLOUR"<<std::endl;
|
std::cout<<"doing conversion MODULATE_ALPHA_BY_COLOUR"<<std::endl;
|
||||||
modifyImage(image,ModulateAlphaByColourOperator(colour));
|
osgVolume::modifyImage(image,ModulateAlphaByColourOperator(colour));
|
||||||
break;
|
break;
|
||||||
case (REPLACE_ALPHA_WITH_LUMINACE):
|
case (REPLACE_ALPHA_WITH_LUMINACE):
|
||||||
std::cout<<"doing conversion REPLACE_ALPHA_WITH_LUMINACE"<<std::endl;
|
std::cout<<"doing conversion REPLACE_ALPHA_WITH_LUMINACE"<<std::endl;
|
||||||
modifyImage(image,ReplaceAlphaWithLuminanceOperator());
|
osgVolume::modifyImage(image,ReplaceAlphaWithLuminanceOperator());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -1603,7 +1484,8 @@ osg::Image* applyTransferFunction(osg::Image* image, osg::TransferFunction1D* tr
|
|||||||
osg::Image* output_image = new osg::Image;
|
osg::Image* output_image = new osg::Image;
|
||||||
output_image->allocateImage(image->s(),image->t(), image->r(), GL_RGBA, GL_UNSIGNED_BYTE);
|
output_image->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;
|
return output_image;
|
||||||
}
|
}
|
||||||
@ -1913,6 +1795,51 @@ int main( int argc, char **argv )
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
osg::RefMatrix* matrix = dynamic_cast<osg::RefMatrix*>(image_3d->getUserData());
|
||||||
|
if (matrix)
|
||||||
|
{
|
||||||
|
osg::notify(osg::NOTICE)<<"Image has Matrix = "<<*matrix<<std::endl;
|
||||||
|
xSize = image_3d->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 "<<minValue<<std::endl;
|
||||||
|
osg::notify(osg::NOTICE)<<"Max value "<<maxValue<<std::endl;
|
||||||
|
|
||||||
|
float minComponent = minValue[0];
|
||||||
|
minComponent = osg::minimum(minComponent,minValue[1]);
|
||||||
|
minComponent = osg::minimum(minComponent,minValue[2]);
|
||||||
|
minComponent = osg::minimum(minComponent,minValue[3]);
|
||||||
|
|
||||||
|
float maxComponent = maxValue[0];
|
||||||
|
maxComponent = osg::maximum(maxComponent,maxValue[1]);
|
||||||
|
maxComponent = osg::maximum(maxComponent,maxValue[2]);
|
||||||
|
maxComponent = osg::maximum(maxComponent,maxValue[3]);
|
||||||
|
|
||||||
|
float scale = 0.99f/(maxComponent-minComponent);
|
||||||
|
float offset = -minComponent * scale;
|
||||||
|
|
||||||
|
osgVolume::offsetAndScaleImage(image_3d.get(),
|
||||||
|
osg::Vec4(offset, offset, offset, offset),
|
||||||
|
osg::Vec4(scale, scale, scale, scale));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
osg::Vec4 newMinValue, newMaxValue;
|
||||||
|
if (osgVolume::computeMinMax(image_3d.get(), newMinValue, newMaxValue));
|
||||||
|
{
|
||||||
|
osg::notify(osg::NOTICE)<<"After min value "<<newMinValue<<std::endl;
|
||||||
|
osg::notify(osg::NOTICE)<<"After max value "<<newMaxValue<<std::endl;
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (colourSpaceOperation!=NO_COLOUR_SPACE_OPERATION)
|
if (colourSpaceOperation!=NO_COLOUR_SPACE_OPERATION)
|
||||||
{
|
{
|
||||||
doColourSpaceConversion(colourSpaceOperation, image_3d.get(), colourModulate);
|
doColourSpaceConversion(colourSpaceOperation, image_3d.get(), colourModulate);
|
||||||
@ -1926,15 +1853,6 @@ int main( int argc, char **argv )
|
|||||||
osg::ref_ptr<osg::Image> normalmap_3d = createNormalMap ? createNormalMapTexture(image_3d.get()) : 0;
|
osg::ref_ptr<osg::Image> normalmap_3d = createNormalMap ? createNormalMapTexture(image_3d.get()) : 0;
|
||||||
|
|
||||||
|
|
||||||
osg::RefMatrix* matrix = dynamic_cast<osg::RefMatrix*>(image_3d->getUserData());
|
|
||||||
if (matrix)
|
|
||||||
{
|
|
||||||
osg::notify(osg::NOTICE)<<"Image has Matrix = "<<*matrix<<std::endl;
|
|
||||||
xSize = image_3d->s() * (*matrix)(0,0);
|
|
||||||
ySize = image_3d->t() * (*matrix)(1,1);
|
|
||||||
zSize = image_3d->r() * (*matrix)(2,2);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// create a model from the images.
|
// create a model from the images.
|
||||||
osg::Node* rootNode = 0;
|
osg::Node* rootNode = 0;
|
||||||
|
47
include/osgVolume/Export
Normal file
47
include/osgVolume/Export
Normal file
@ -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
|
132
include/osgVolume/ImageUtils
Normal file
132
include/osgVolume/ImageUtils
Normal file
@ -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 <osgVolume/Export>
|
||||||
|
|
||||||
|
#include <osg/Image>
|
||||||
|
|
||||||
|
namespace osgVolume {
|
||||||
|
|
||||||
|
template <typename T, class O>
|
||||||
|
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<num;++i) { float l = float(*data++)*scale; operation.luminance(l); } } break;
|
||||||
|
case(GL_ALPHA): { for(unsigned int i=0;i<num;++i) { float a = float(*data++)*scale; operation.alpha(a); } } break;
|
||||||
|
case(GL_LUMINANCE_ALPHA): { for(unsigned int i=0;i<num;++i) { float l = float(*data++)*scale; float a = float(*data++)*scale; operation.luminance_alpha(l,a); } } break;
|
||||||
|
case(GL_RGB): { for(unsigned int i=0;i<num;++i) { float r = float(*data++)*scale; float g = float(*data++)*scale; float b = float(*data++)*scale; operation.rgb(r,g,b); } } break;
|
||||||
|
case(GL_RGBA): { for(unsigned int i=0;i<num;++i) { float r = float(*data++)*scale; float g = float(*data++)*scale; float b = float(*data++)*scale; float a = float(*data++)*scale; operation.rgba(r,g,b,a); } } break;
|
||||||
|
case(GL_BGR): { for(unsigned int i=0;i<num;++i) { float b = float(*data++)*scale; float g = float(*data++)*scale; float r = float(*data++)*scale; operation.rgb(r,g,b); } } break;
|
||||||
|
case(GL_BGRA): { for(unsigned int i=0;i<num;++i) { float b = float(*data++)*scale; float g = float(*data++)*scale; float r = float(*data++)*scale; float a = float(*data++)*scale; operation.rgba(r,g,b,a); } } break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class O>
|
||||||
|
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 <class O>
|
||||||
|
void readImage(const osg::Image* image, O& operation)
|
||||||
|
{
|
||||||
|
if (!image) return;
|
||||||
|
|
||||||
|
for(int r=0;r<image->r();++r)
|
||||||
|
{
|
||||||
|
for(int t=0;t<image->t();++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 <typename T, class M>
|
||||||
|
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<num;++i) { float l = float(*data)*scale; operation.luminance(l); *data++ = T(l*inv_scale); } } break;
|
||||||
|
case(GL_ALPHA): { for(unsigned int i=0;i<num;++i) { float a = float(*data)*scale; operation.alpha(a); *data++ = T(a*inv_scale); } } break;
|
||||||
|
case(GL_LUMINANCE_ALPHA): { for(unsigned int i=0;i<num;++i) { float l = float(*data)*scale; float a = float(*(data+1))*scale; operation.luminance_alpha(l,a); *data++ = T(l*inv_scale); *data++ = T(a*inv_scale); } } break;
|
||||||
|
case(GL_RGB): { for(unsigned int i=0;i<num;++i) { float r = float(*data)*scale; float g = float(*(data+1))*scale; float b = float(*(data+2))*scale; operation.rgb(r,g,b); *data++ = T(r*inv_scale); *data++ = T(g*inv_scale); *data++ = T(b*inv_scale); } } break;
|
||||||
|
case(GL_RGBA): { for(unsigned int i=0;i<num;++i) { float r = float(*data)*scale; float g = float(*(data+1))*scale; float b = float(*(data+2))*scale; float a = float(*(data+3))*scale; operation.rgba(r,g,b,a); *data++ = T(r*inv_scale); *data++ = T(g*inv_scale); *data++ = T(g*inv_scale); *data++ = T(a*inv_scale); } } break;
|
||||||
|
case(GL_BGR): { for(unsigned int i=0;i<num;++i) { float b = float(*data)*scale; float g = float(*(data+1))*scale; float r = float(*(data+2))*scale; operation.rgb(r,g,b); *data++ = T(b*inv_scale); *data++ = T(g*inv_scale); *data++ = T(r*inv_scale); } } break;
|
||||||
|
case(GL_BGRA): { for(unsigned int i=0;i<num;++i) { float b = float(*data)*scale; float g = float(*(data+1))*scale; float r = float(*(data+2))*scale; float a = float(*(data+3))*scale; operation.rgba(r,g,b,a); *data++ = T(g*inv_scale); *data++ = T(b*inv_scale); *data++ = T(r*inv_scale); *data++ = T(a*inv_scale); } } break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class M>
|
||||||
|
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 <class M>
|
||||||
|
void modifyImage(osg::Image* image, const M& operation)
|
||||||
|
{
|
||||||
|
if (!image) return;
|
||||||
|
|
||||||
|
for(int r=0;r<image->r();++r)
|
||||||
|
{
|
||||||
|
for(int t=0;t<image->t();++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
|
46
include/osgVolume/Version
Normal file
46
include/osgVolume/Version
Normal file
@ -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 <osgVolume/Export>
|
||||||
|
|
||||||
|
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
|
@ -12,6 +12,7 @@ FOREACH( mylibfolder
|
|||||||
osgParticle
|
osgParticle
|
||||||
osgShadow
|
osgShadow
|
||||||
osgTerrain
|
osgTerrain
|
||||||
|
osgVolume
|
||||||
osgViewer
|
osgViewer
|
||||||
)
|
)
|
||||||
|
|
||||||
|
33
src/osgVolume/CMakeLists.txt
Normal file
33
src/osgVolume/CMakeLists.txt
Normal file
@ -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)
|
123
src/osgVolume/ImageUtils.cpp
Normal file
123
src/osgVolume/ImageUtils.cpp
Normal file
@ -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 <float.h>
|
||||||
|
#include <osg/Math>
|
||||||
|
#include <osg/Notify>
|
||||||
|
#include <osgVolume/ImageUtils>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
30
src/osgVolume/Version.cpp
Normal file
30
src/osgVolume/Version.cpp
Normal file
@ -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 <osgVolume/Version>
|
||||||
|
#include <osg/Version>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
const char* osgVolumeGetVersion()
|
||||||
|
{
|
||||||
|
return osgGetVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char* osgVolumeGetLibraryName()
|
||||||
|
{
|
||||||
|
return "OpenSceneGraph Volume Library";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user