2007-06-12 22:20:16 +08:00
/* OpenSceneGraph example, osgvolume.
*
* Permission is hereby granted , free of charge , to any person obtaining a copy
* of this software and associated documentation files ( the " Software " ) , to deal
* in the Software without restriction , including without limitation the rights
* to use , copy , modify , merge , publish , distribute , sublicense , and / or sell
* copies of the Software , and to permit persons to whom the Software is
* furnished to do so , subject to the following conditions :
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
* LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM ,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE .
*/
2004-06-29 21:59:07 +08:00
# include <osg/Node>
# include <osg/Geometry>
# include <osg/Notify>
# include <osg/Texture3D>
2008-09-24 18:45:15 +08:00
# include <osg/Texture1D>
2008-09-29 18:56:42 +08:00
# include <osg/ImageSequence>
2004-06-29 21:59:07 +08:00
# include <osg/TexGen>
# include <osg/Geode>
# include <osg/Billboard>
# include <osg/PositionAttitudeTransform>
# include <osg/ClipNode>
# include <osg/AlphaFunc>
# include <osg/TexGenNode>
2005-05-02 03:48:49 +08:00
# include <osg/TexEnv>
2004-06-29 21:59:07 +08:00
# include <osg/TexEnvCombine>
2004-07-07 23:05:00 +08:00
# include <osg/Material>
2005-09-05 17:14:30 +08:00
# include <osg/PrimitiveSet>
2005-02-01 04:09:24 +08:00
# include <osg/Endian>
2008-08-18 23:08:04 +08:00
# include <osg/BlendFunc>
# include <osg/BlendEquation>
2008-09-12 23:41:30 +08:00
# include <osg/TransferFunction>
2008-10-02 23:45:08 +08:00
# include <osg/MatrixTransform>
2004-06-29 21:59:07 +08:00
# include <osgDB/Registry>
# include <osgDB/ReadFile>
# include <osgDB/WriteFile>
2005-09-05 15:48:55 +08:00
# include <osgDB/FileUtils>
2004-06-29 21:59:07 +08:00
# include <osgDB/FileNameUtils>
2005-09-05 21:19:20 +08:00
# include <osgGA/EventVisitor>
2008-09-29 18:56:42 +08:00
# include <osgGA/TrackballManipulator>
# include <osgGA/FlightManipulator>
# include <osgGA/KeySwitchMatrixManipulator>
2005-09-05 21:19:20 +08:00
2004-06-29 21:59:07 +08:00
# include <osgUtil/CullVisitor>
2007-01-11 23:19:59 +08:00
# include <osgViewer/Viewer>
2008-08-27 01:40:04 +08:00
# include <osgViewer/ViewerEventHandlers>
2007-01-11 23:19:59 +08:00
2009-07-03 02:50:45 +08:00
# include <osgManipulator/TabBoxDragger>
2009-07-03 13:54:27 +08:00
# include <osgManipulator/TabPlaneTrackballDragger>
# include <osgManipulator/TrackballDragger>
2009-07-03 02:50:45 +08:00
2008-08-23 00:35:49 +08:00
# include <osg/io_utils>
2008-09-13 21:38:06 +08:00
# include <algorithm>
2007-01-11 23:19:59 +08:00
# include <iostream>
2004-06-29 21:59:07 +08:00
2009-01-09 23:19:25 +08:00
# include <osg/ImageUtils>
# include <osgVolume/Volume>
# include <osgVolume/VolumeTile>
2009-01-21 22:27:58 +08:00
# include <osgVolume/RayTracedTechnique>
2009-01-14 01:20:32 +08:00
# include <osgVolume/FixedFunctionTechnique>
2004-06-29 21:59:07 +08:00
typedef std : : vector < osg : : ref_ptr < osg : : Image > > ImageList ;
2008-09-26 19:29:00 +08:00
enum ShadingModel
{
Standard ,
Light ,
Isosurface ,
MaximumIntensityProjection
} ;
2004-06-29 21:59:07 +08:00
struct PassThroughTransformFunction
{
unsigned char operator ( ) ( unsigned char c ) const { return c ; }
} ;
struct ProcessRow
{
2005-11-10 17:42:34 +08:00
virtual ~ ProcessRow ( ) { }
2004-06-29 21:59:07 +08:00
virtual void operator ( ) ( unsigned int num ,
2009-09-01 18:48:32 +08:00
GLenum source_pixelFormat , unsigned char * source ,
GLenum dest_pixelFormat , unsigned char * dest ) const
2004-06-29 21:59:07 +08:00
{
switch ( source_pixelFormat )
{
case ( GL_LUMINANCE ) :
case ( GL_ALPHA ) :
switch ( dest_pixelFormat )
{
2009-09-01 18:48:32 +08:00
case ( GL_LUMINANCE ) :
2004-06-29 21:59:07 +08:00
case ( GL_ALPHA ) : A_to_A ( num , source , dest ) ; break ;
case ( GL_LUMINANCE_ALPHA ) : A_to_LA ( num , source , dest ) ; break ;
case ( GL_RGB ) : A_to_RGB ( num , source , dest ) ; break ;
case ( GL_RGBA ) : A_to_RGBA ( num , source , dest ) ; break ;
}
break ;
case ( GL_LUMINANCE_ALPHA ) :
switch ( dest_pixelFormat )
{
2009-09-01 18:48:32 +08:00
case ( GL_LUMINANCE ) :
2004-06-29 21:59:07 +08:00
case ( GL_ALPHA ) : LA_to_A ( num , source , dest ) ; break ;
case ( GL_LUMINANCE_ALPHA ) : LA_to_LA ( num , source , dest ) ; break ;
case ( GL_RGB ) : LA_to_RGB ( num , source , dest ) ; break ;
case ( GL_RGBA ) : LA_to_RGBA ( num , source , dest ) ; break ;
}
break ;
case ( GL_RGB ) :
switch ( dest_pixelFormat )
{
2009-09-01 18:48:32 +08:00
case ( GL_LUMINANCE ) :
2004-06-29 21:59:07 +08:00
case ( GL_ALPHA ) : RGB_to_A ( num , source , dest ) ; break ;
case ( GL_LUMINANCE_ALPHA ) : RGB_to_LA ( num , source , dest ) ; break ;
case ( GL_RGB ) : RGB_to_RGB ( num , source , dest ) ; break ;
case ( GL_RGBA ) : RGB_to_RGBA ( num , source , dest ) ; break ;
}
break ;
case ( GL_RGBA ) :
switch ( dest_pixelFormat )
{
2009-09-01 18:48:32 +08:00
case ( GL_LUMINANCE ) :
2004-06-29 21:59:07 +08:00
case ( GL_ALPHA ) : RGBA_to_A ( num , source , dest ) ; break ;
case ( GL_LUMINANCE_ALPHA ) : RGBA_to_LA ( num , source , dest ) ; break ;
case ( GL_RGB ) : RGBA_to_RGB ( num , source , dest ) ; break ;
case ( GL_RGBA ) : RGBA_to_RGBA ( num , source , dest ) ; break ;
}
break ;
}
}
///////////////////////////////////////////////////////////////////////////////
2009-09-01 18:48:32 +08:00
// alpha sources..
2004-06-29 21:59:07 +08:00
virtual void A_to_A ( unsigned int num , unsigned char * source , unsigned char * dest ) const
{
for ( unsigned int i = 0 ; i < num ; + + i )
{
* dest + + = * source + + ;
}
}
virtual void A_to_LA ( unsigned int num , unsigned char * source , unsigned char * dest ) const
{
for ( unsigned int i = 0 ; i < num ; + + i )
{
* dest + + = * source ;
* dest + + = * source + + ;
}
}
2009-09-01 18:48:32 +08:00
2004-06-29 21:59:07 +08:00
virtual void A_to_RGB ( unsigned int num , unsigned char * source , unsigned char * dest ) const
{
for ( unsigned int i = 0 ; i < num ; + + i )
{
* dest + + = * source ;
* dest + + = * source ;
* dest + + = * source + + ;
}
}
virtual void A_to_RGBA ( unsigned int num , unsigned char * source , unsigned char * dest ) const
{
for ( unsigned int i = 0 ; i < num ; + + i )
{
* dest + + = * source ;
* dest + + = * source ;
* dest + + = * source ;
* dest + + = * source + + ;
}
}
///////////////////////////////////////////////////////////////////////////////
2009-09-01 18:48:32 +08:00
// alpha luminance sources..
2004-06-29 21:59:07 +08:00
virtual void LA_to_A ( unsigned int num , unsigned char * source , unsigned char * dest ) const
{
for ( unsigned int i = 0 ; i < num ; + + i )
{
+ + source ;
* dest + + = * source + + ;
}
}
virtual void LA_to_LA ( unsigned int num , unsigned char * source , unsigned char * dest ) const
{
for ( unsigned int i = 0 ; i < num ; + + i )
{
* dest + + = * source + + ;
* dest + + = * source + + ;
}
}
2009-09-01 18:48:32 +08:00
2004-06-29 21:59:07 +08:00
virtual void LA_to_RGB ( unsigned int num , unsigned char * source , unsigned char * dest ) const
{
for ( unsigned int i = 0 ; i < num ; + + i )
{
* dest + + = * source ;
* dest + + = * source ;
* dest + + = * source ;
source + = 2 ;
}
}
virtual void LA_to_RGBA ( unsigned int num , unsigned char * source , unsigned char * dest ) const
{
for ( unsigned int i = 0 ; i < num ; + + i )
{
* dest + + = * source ;
* dest + + = * source ;
* dest + + = * source + + ;
* dest + + = * source + + ;
}
}
///////////////////////////////////////////////////////////////////////////////
2009-09-01 18:48:32 +08:00
// RGB sources..
2004-06-29 21:59:07 +08:00
virtual void RGB_to_A ( unsigned int num , unsigned char * source , unsigned char * dest ) const
{
for ( unsigned int i = 0 ; i < num ; + + i )
{
unsigned char val = * source ;
* dest + + = val ;
source + = 3 ;
}
}
virtual void RGB_to_LA ( unsigned int num , unsigned char * source , unsigned char * dest ) const
{
for ( unsigned int i = 0 ; i < num ; + + i )
{
unsigned char val = * source ;
* dest + + = val ;
* dest + + = val ;
source + = 3 ;
}
}
2009-09-01 18:48:32 +08:00
2004-06-29 21:59:07 +08:00
virtual void RGB_to_RGB ( unsigned int num , unsigned char * source , unsigned char * dest ) const
{
for ( unsigned int i = 0 ; i < num ; + + i )
{
* dest + + = * source + + ;
* dest + + = * source + + ;
* dest + + = * source + + ;
}
}
virtual void RGB_to_RGBA ( unsigned int num , unsigned char * source , unsigned char * dest ) const
{
for ( unsigned int i = 0 ; i < num ; + + i )
{
unsigned char val = * source ;
* dest + + = * source + + ;
* dest + + = * source + + ;
* dest + + = * source + + ;
* dest + + = val ;
}
}
///////////////////////////////////////////////////////////////////////////////
2009-09-01 18:48:32 +08:00
// RGBA sources..
2004-06-29 21:59:07 +08:00
virtual void RGBA_to_A ( unsigned int num , unsigned char * source , unsigned char * dest ) const
{
for ( unsigned int i = 0 ; i < num ; + + i )
{
source + = 3 ;
* dest + + = * source + + ;
}
}
virtual void RGBA_to_LA ( unsigned int num , unsigned char * source , unsigned char * dest ) const
{
for ( unsigned int i = 0 ; i < num ; + + i )
{
unsigned char val = * source ;
source + = 3 ;
* dest + + = val ;
* dest + + = * source + + ;
}
}
2009-09-01 18:48:32 +08:00
2004-06-29 21:59:07 +08:00
virtual void RGBA_to_RGB ( unsigned int num , unsigned char * source , unsigned char * dest ) const
{
for ( unsigned int i = 0 ; i < num ; + + i )
{
* dest + + = * source + + ;
* dest + + = * source + + ;
* dest + + = * source + + ;
+ + source ;
}
}
virtual void RGBA_to_RGBA ( unsigned int num , unsigned char * source , unsigned char * dest ) const
{
for ( unsigned int i = 0 ; i < num ; + + i )
{
* dest + + = * source + + ;
* dest + + = * source + + ;
* dest + + = * source + + ;
* dest + + = * source + + ;
}
}
} ;
2005-02-01 04:09:24 +08:00
void clampToNearestValidPowerOfTwo ( int & sizeX , int & sizeY , int & sizeZ , int s_maximumTextureSize , int t_maximumTextureSize , int r_maximumTextureSize )
{
// compute nearest powers of two for each axis.
int s_nearestPowerOfTwo = 1 ;
while ( s_nearestPowerOfTwo < sizeX & & s_nearestPowerOfTwo < s_maximumTextureSize ) s_nearestPowerOfTwo * = 2 ;
int t_nearestPowerOfTwo = 1 ;
while ( t_nearestPowerOfTwo < sizeY & & t_nearestPowerOfTwo < t_maximumTextureSize ) t_nearestPowerOfTwo * = 2 ;
int r_nearestPowerOfTwo = 1 ;
while ( r_nearestPowerOfTwo < sizeZ & & r_nearestPowerOfTwo < r_maximumTextureSize ) r_nearestPowerOfTwo * = 2 ;
sizeX = s_nearestPowerOfTwo ;
sizeY = t_nearestPowerOfTwo ;
sizeZ = r_nearestPowerOfTwo ;
}
2009-09-01 18:48:32 +08:00
osg : : Image * createTexture3D ( ImageList & imageList , ProcessRow & processRow ,
unsigned int numComponentsDesired ,
2004-09-04 17:22:26 +08:00
int s_maximumTextureSize ,
int t_maximumTextureSize ,
2008-09-12 23:41:30 +08:00
int r_maximumTextureSize ,
bool resizeToPowerOfTwo )
2004-06-29 21:59:07 +08:00
{
int max_s = 0 ;
int max_t = 0 ;
unsigned int max_components = 0 ;
int total_r = 0 ;
ImageList : : iterator itr ;
2004-07-09 23:42:07 +08:00
for ( itr = imageList . begin ( ) ;
2004-06-29 21:59:07 +08:00
itr ! = imageList . end ( ) ;
+ + itr )
{
osg : : Image * image = itr - > get ( ) ;
GLenum pixelFormat = image - > getPixelFormat ( ) ;
2009-09-01 18:48:32 +08:00
if ( pixelFormat = = GL_ALPHA | |
pixelFormat = = GL_INTENSITY | |
pixelFormat = = GL_LUMINANCE | |
pixelFormat = = GL_LUMINANCE_ALPHA | |
pixelFormat = = GL_RGB | |
2004-06-29 21:59:07 +08:00
pixelFormat = = GL_RGBA )
{
2004-07-09 23:42:07 +08:00
max_s = osg : : maximum ( image - > s ( ) , max_s ) ;
max_t = osg : : maximum ( image - > t ( ) , max_t ) ;
max_components = osg : : maximum ( osg : : Image : : computeNumComponents ( pixelFormat ) , max_components ) ;
2004-06-29 21:59:07 +08:00
total_r + = image - > r ( ) ;
}
else
{
osg : : notify ( osg : : NOTICE ) < < " Image " < < image - > getFileName ( ) < < " has unsuitable pixel format " < < std : : hex < < pixelFormat < < std : : dec < < std : : endl ;
}
}
2009-09-01 18:48:32 +08:00
2004-06-29 21:59:07 +08:00
if ( numComponentsDesired ! = 0 ) max_components = numComponentsDesired ;
2009-09-01 18:48:32 +08:00
2004-06-29 21:59:07 +08:00
GLenum desiredPixelFormat = 0 ;
switch ( max_components )
{
case ( 1 ) :
2004-09-03 18:02:56 +08:00
osg : : notify ( osg : : NOTICE ) < < " desiredPixelFormat = GL_LUMINANCE " < < std : : endl ;
2004-06-29 21:59:07 +08:00
desiredPixelFormat = GL_LUMINANCE ;
break ;
case ( 2 ) :
2004-09-03 18:02:56 +08:00
osg : : notify ( osg : : NOTICE ) < < " desiredPixelFormat = GL_LUMINANCE_ALPHA " < < std : : endl ;
2004-06-29 21:59:07 +08:00
desiredPixelFormat = GL_LUMINANCE_ALPHA ;
break ;
case ( 3 ) :
2004-09-03 18:02:56 +08:00
osg : : notify ( osg : : NOTICE ) < < " desiredPixelFormat = GL_RGB " < < std : : endl ;
2004-06-29 21:59:07 +08:00
desiredPixelFormat = GL_RGB ;
break ;
case ( 4 ) :
2004-09-03 18:02:56 +08:00
osg : : notify ( osg : : NOTICE ) < < " desiredPixelFormat = GL_RGBA " < < std : : endl ;
2004-06-29 21:59:07 +08:00
desiredPixelFormat = GL_RGBA ;
break ;
2009-09-01 18:48:32 +08:00
}
2004-06-29 21:59:07 +08:00
if ( desiredPixelFormat = = 0 ) return 0 ;
2009-09-01 18:48:32 +08:00
2004-06-29 21:59:07 +08:00
// compute nearest powers of two for each axis.
2009-09-01 18:48:32 +08:00
2004-06-29 21:59:07 +08:00
int s_nearestPowerOfTwo = 1 ;
int t_nearestPowerOfTwo = 1 ;
int r_nearestPowerOfTwo = 1 ;
2004-09-03 18:02:56 +08:00
2008-09-12 23:41:30 +08:00
if ( resizeToPowerOfTwo )
{
while ( s_nearestPowerOfTwo < max_s & & s_nearestPowerOfTwo < s_maximumTextureSize ) s_nearestPowerOfTwo * = 2 ;
while ( t_nearestPowerOfTwo < max_t & & t_nearestPowerOfTwo < t_maximumTextureSize ) t_nearestPowerOfTwo * = 2 ;
while ( r_nearestPowerOfTwo < total_r & & r_nearestPowerOfTwo < r_maximumTextureSize ) r_nearestPowerOfTwo * = 2 ;
2004-09-03 18:02:56 +08:00
2008-09-12 23:41:30 +08:00
osg : : notify ( osg : : NOTICE ) < < " max image width = " < < max_s < < " nearest power of two = " < < s_nearestPowerOfTwo < < std : : endl ;
osg : : notify ( osg : : NOTICE ) < < " max image height = " < < max_t < < " nearest power of two = " < < t_nearestPowerOfTwo < < std : : endl ;
osg : : notify ( osg : : NOTICE ) < < " max image depth = " < < total_r < < " nearest power of two = " < < r_nearestPowerOfTwo < < std : : endl ;
}
else
{
s_nearestPowerOfTwo = max_s ;
t_nearestPowerOfTwo = max_t ;
r_nearestPowerOfTwo = total_r ;
}
2009-09-01 18:48:32 +08:00
2004-06-29 21:59:07 +08:00
// now allocate the 3d texture;
osg : : ref_ptr < osg : : Image > image_3d = new osg : : Image ;
image_3d - > allocateImage ( s_nearestPowerOfTwo , t_nearestPowerOfTwo , r_nearestPowerOfTwo ,
desiredPixelFormat , GL_UNSIGNED_BYTE ) ;
2009-09-01 18:48:32 +08:00
2004-06-29 21:59:07 +08:00
2004-09-03 23:42:43 +08:00
unsigned int r_offset = ( total_r < r_nearestPowerOfTwo ) ? r_nearestPowerOfTwo / 2 - total_r / 2 : 0 ;
int curr_dest_r = r_offset ;
// copy across the values from the source images into the image_3d.
2004-07-09 23:42:07 +08:00
for ( itr = imageList . begin ( ) ;
2004-06-29 21:59:07 +08:00
itr ! = imageList . end ( ) ;
+ + itr )
{
osg : : Image * image = itr - > get ( ) ;
GLenum pixelFormat = image - > getPixelFormat ( ) ;
2009-09-01 18:48:32 +08:00
if ( pixelFormat = = GL_ALPHA | |
pixelFormat = = GL_LUMINANCE | |
pixelFormat = = GL_INTENSITY | |
pixelFormat = = GL_LUMINANCE_ALPHA | |
pixelFormat = = GL_RGB | |
2004-06-29 21:59:07 +08:00
pixelFormat = = GL_RGBA )
{
2009-09-01 18:48:32 +08:00
2004-07-09 23:26:48 +08:00
int num_r = osg : : minimum ( image - > r ( ) , ( image_3d - > r ( ) - curr_dest_r ) ) ;
int num_t = osg : : minimum ( image - > t ( ) , image_3d - > t ( ) ) ;
int num_s = osg : : minimum ( image - > s ( ) , image_3d - > s ( ) ) ;
2009-09-01 18:48:32 +08:00
2005-11-18 04:22:55 +08:00
unsigned int s_offset_dest = ( image - > s ( ) < s_nearestPowerOfTwo ) ? s_nearestPowerOfTwo / 2 - image - > s ( ) / 2 : 0 ;
unsigned int t_offset_dest = ( image - > t ( ) < t_nearestPowerOfTwo ) ? t_nearestPowerOfTwo / 2 - image - > t ( ) / 2 : 0 ;
2004-09-03 23:42:43 +08:00
2004-06-29 21:59:07 +08:00
for ( int r = 0 ; r < num_r ; + + r , + + curr_dest_r )
{
for ( int t = 0 ; t < num_t ; + + t )
{
2004-09-03 23:42:43 +08:00
unsigned char * dest = image_3d - > data ( s_offset_dest , t + t_offset_dest , curr_dest_r ) ;
2004-06-29 21:59:07 +08:00
unsigned char * source = image - > data ( 0 , t , r ) ;
processRow ( num_s , image - > getPixelFormat ( ) , source , image_3d - > getPixelFormat ( ) , dest ) ;
}
}
}
2009-09-01 18:48:32 +08:00
}
2004-06-29 21:59:07 +08:00
return image_3d . release ( ) ;
}
2005-02-01 04:09:24 +08:00
struct ScaleOperator
{
2005-02-02 06:36:05 +08:00
ScaleOperator ( ) : _scale ( 1.0f ) { }
2005-02-01 04:09:24 +08:00
ScaleOperator ( float scale ) : _scale ( scale ) { }
2005-02-02 06:36:05 +08:00
ScaleOperator ( const ScaleOperator & so ) : _scale ( so . _scale ) { }
2009-09-01 18:48:32 +08:00
2005-02-02 06:36:05 +08:00
ScaleOperator & operator = ( const ScaleOperator & so ) { _scale = so . _scale ; return * this ; }
2005-02-01 04:09:24 +08:00
float _scale ;
2009-09-01 18:48:32 +08:00
inline void luminance ( float & l ) const { l * = _scale ; }
inline void alpha ( float & a ) const { a * = _scale ; }
inline void luminance_alpha ( float & l , float & a ) const { l * = _scale ; a * = _scale ; }
2005-02-01 04:09:24 +08:00
inline void rgb ( float & r , float & g , float & b ) const { r * = _scale ; g * = _scale ; b * = _scale ; }
inline void rgba ( float & r , float & g , float & b , float & a ) const { r * = _scale ; g * = _scale ; b * = _scale ; a * = _scale ; }
} ;
2005-02-01 17:02:01 +08:00
struct RecordRowOperator
{
RecordRowOperator ( unsigned int num ) : _colours ( num ) , _pos ( 0 ) { }
mutable std : : vector < osg : : Vec4 > _colours ;
mutable unsigned int _pos ;
2009-09-01 18:48:32 +08:00
inline void luminance ( float l ) const { rgba ( l , l , l , 1.0f ) ; }
inline void alpha ( float a ) const { rgba ( 1.0f , 1.0f , 1.0f , a ) ; }
inline void luminance_alpha ( float l , float a ) const { rgba ( l , l , l , a ) ; }
2005-02-01 17:02:01 +08:00
inline void rgb ( float r , float g , float b ) const { rgba ( r , g , b , 1.0f ) ; }
inline void rgba ( float r , float g , float b , float a ) const { _colours [ _pos + + ] . set ( r , g , b , a ) ; }
} ;
struct WriteRowOperator
{
WriteRowOperator ( ) : _pos ( 0 ) { }
WriteRowOperator ( unsigned int num ) : _colours ( num ) , _pos ( 0 ) { }
std : : vector < osg : : Vec4 > _colours ;
mutable unsigned int _pos ;
2009-09-01 18:48:32 +08:00
inline void luminance ( float & l ) const { l = _colours [ _pos + + ] . r ( ) ; }
inline void alpha ( float & a ) const { a = _colours [ _pos + + ] . a ( ) ; }
inline void luminance_alpha ( float & l , float & a ) const { l = _colours [ _pos ] . r ( ) ; a = _colours [ _pos + + ] . a ( ) ; }
2005-09-04 04:56:25 +08:00
inline void rgb ( float & r , float & g , float & b ) const { r = _colours [ _pos ] . r ( ) ; g = _colours [ _pos ] . g ( ) ; b = _colours [ _pos ] . b ( ) ; }
inline void rgba ( float & r , float & g , float & b , float & a ) const { r = _colours [ _pos ] . r ( ) ; g = _colours [ _pos ] . g ( ) ; b = _colours [ _pos ] . b ( ) ; a = _colours [ _pos + + ] . a ( ) ; }
2005-02-01 17:02:01 +08:00
} ;
2005-02-01 04:09:24 +08:00
osg : : Image * readRaw ( int sizeX , int sizeY , int sizeZ , int numberBytesPerComponent , int numberOfComponents , const std : : string & endian , const std : : string & raw_filename )
{
2008-11-07 23:08:08 +08:00
osgDB : : ifstream fin ( raw_filename . c_str ( ) , std : : ifstream : : binary ) ;
2005-02-01 04:09:24 +08:00
if ( ! fin ) return 0 ;
GLenum pixelFormat ;
switch ( numberOfComponents )
{
case 1 : pixelFormat = GL_LUMINANCE ; break ;
case 2 : pixelFormat = GL_LUMINANCE_ALPHA ; break ;
case 3 : pixelFormat = GL_RGB ; break ;
case 4 : pixelFormat = GL_RGBA ; break ;
default :
osg : : notify ( osg : : NOTICE ) < < " Error: numberOfComponents= " < < numberOfComponents < < " not supported, only 1,2,3 or 4 are supported. " < < std : : endl ;
return 0 ;
}
2009-09-01 18:48:32 +08:00
2005-02-01 04:09:24 +08:00
GLenum dataType ;
switch ( numberBytesPerComponent )
{
case 1 : dataType = GL_UNSIGNED_BYTE ; break ;
case 2 : dataType = GL_UNSIGNED_SHORT ; break ;
case 4 : dataType = GL_UNSIGNED_INT ; break ;
2009-09-01 18:48:32 +08:00
default :
2005-02-01 04:09:24 +08:00
osg : : notify ( osg : : NOTICE ) < < " Error: numberBytesPerComponent= " < < numberBytesPerComponent < < " not supported, only 1,2 or 4 are supported. " < < std : : endl ;
return 0 ;
}
2009-09-01 18:48:32 +08:00
2005-02-01 04:09:24 +08:00
int s_maximumTextureSize = 256 , t_maximumTextureSize = 256 , r_maximumTextureSize = 256 ;
2009-09-01 18:48:32 +08:00
2005-02-01 04:09:24 +08:00
int sizeS = sizeX ;
int sizeT = sizeY ;
int sizeR = sizeZ ;
clampToNearestValidPowerOfTwo ( sizeS , sizeT , sizeR , s_maximumTextureSize , t_maximumTextureSize , r_maximumTextureSize ) ;
osg : : ref_ptr < osg : : Image > image = new osg : : Image ;
image - > allocateImage ( sizeS , sizeT , sizeR , pixelFormat , dataType ) ;
2009-09-01 18:48:32 +08:00
2005-02-02 06:36:05 +08:00
bool endianSwap = ( osg : : getCpuByteOrder ( ) = = osg : : BigEndian ) ? ( endian ! = " big " ) : ( endian = = " big " ) ;
2009-09-01 18:48:32 +08:00
2005-02-01 04:09:24 +08:00
unsigned int r_offset = ( sizeZ < sizeR ) ? sizeR / 2 - sizeZ / 2 : 0 ;
2009-09-01 18:48:32 +08:00
2005-02-01 04:09:24 +08:00
int offset = endianSwap ? numberBytesPerComponent : 0 ;
int delta = endianSwap ? - 1 : 1 ;
for ( int r = 0 ; r < sizeZ ; + + r )
{
for ( int t = 0 ; t < sizeY ; + + t )
{
char * data = ( char * ) image - > data ( 0 , t , r + r_offset ) ;
for ( int s = 0 ; s < sizeX ; + + s )
{
if ( ! fin ) return 0 ;
2009-09-01 18:48:32 +08:00
2005-02-01 04:09:24 +08:00
for ( int c = 0 ; c < numberOfComponents ; + + c )
{
char * ptr = data + offset ;
for ( int b = 0 ; b < numberBytesPerComponent ; + + b )
{
fin . read ( ( char * ) ptr , 1 ) ;
ptr + = delta ;
}
data + = numberBytesPerComponent ;
}
}
}
}
2005-02-01 17:38:07 +08:00
// normalise texture
2005-02-01 04:09:24 +08:00
{
2005-02-01 17:38:07 +08:00
// compute range of values
2008-09-16 23:32:23 +08:00
osg : : Vec4 minValue , maxValue ;
2009-01-09 23:19:25 +08:00
osg : : computeMinMax ( image . get ( ) , minValue , maxValue ) ;
2009-09-01 18:48:32 +08:00
osg : : modifyImage ( image . get ( ) , ScaleOperator ( 1.0f / maxValue . r ( ) ) ) ;
2005-02-01 04:09:24 +08:00
}
2009-09-01 18:48:32 +08:00
2005-02-01 04:09:24 +08:00
fin . close ( ) ;
2005-02-01 17:02:01 +08:00
if ( dataType ! = GL_UNSIGNED_BYTE )
{
// need to convert to ubyte
2009-09-01 18:48:32 +08:00
2005-02-01 17:38:07 +08:00
osg : : ref_ptr < osg : : Image > new_image = new osg : : Image ;
new_image - > allocateImage ( sizeS , sizeT , sizeR , pixelFormat , GL_UNSIGNED_BYTE ) ;
2009-09-01 18:48:32 +08:00
2005-02-01 17:38:07 +08:00
RecordRowOperator readOp ( sizeS ) ;
WriteRowOperator writeOp ;
for ( int r = 0 ; r < sizeR ; + + r )
{
for ( int t = 0 ; t < sizeT ; + + t )
{
2007-12-11 01:30:18 +08:00
// reset the indices to beginning
2005-02-01 17:38:07 +08:00
readOp . _pos = 0 ;
writeOp . _pos = 0 ;
2009-09-01 18:48:32 +08:00
2005-02-01 17:38:07 +08:00
// read the pixels into readOp's _colour array
2009-01-09 23:19:25 +08:00
osg : : readRow ( sizeS , pixelFormat , dataType , image - > data ( 0 , t , r ) , readOp ) ;
2009-09-01 18:48:32 +08:00
2005-02-01 17:38:07 +08:00
// pass readOp's _colour array contents over to writeOp (note this is just a pointer swap).
writeOp . _colours . swap ( readOp . _colours ) ;
2009-09-01 18:48:32 +08:00
2009-01-09 23:19:25 +08:00
osg : : modifyRow ( sizeS , pixelFormat , GL_UNSIGNED_BYTE , new_image - > data ( 0 , t , r ) , writeOp ) ;
2005-02-01 17:38:07 +08:00
// return readOp's _colour array contents back to its rightful owner.
writeOp . _colours . swap ( readOp . _colours ) ;
}
}
2009-09-01 18:48:32 +08:00
2005-02-01 17:38:07 +08:00
image = new_image ;
2005-02-01 17:02:01 +08:00
}
2009-09-01 18:48:32 +08:00
2005-02-01 04:09:24 +08:00
return image . release ( ) ;
2009-09-01 18:48:32 +08:00
2005-02-01 04:09:24 +08:00
}
2004-06-29 21:59:07 +08:00
2005-02-02 06:36:05 +08:00
enum ColourSpaceOperation
{
NO_COLOUR_SPACE_OPERATION ,
MODULATE_ALPHA_BY_LUMINANCE ,
MODULATE_ALPHA_BY_COLOUR ,
2009-08-19 23:36:46 +08:00
REPLACE_ALPHA_WITH_LUMINANCE ,
2008-11-05 23:04:38 +08:00
REPLACE_RGB_WITH_LUMINANCE
2005-02-02 06:36:05 +08:00
} ;
2005-02-01 17:02:01 +08:00
2005-09-04 04:56:25 +08:00
struct ModulateAlphaByLuminanceOperator
2004-06-29 21:59:07 +08:00
{
2005-09-04 04:56:25 +08:00
ModulateAlphaByLuminanceOperator ( ) { }
2004-06-29 21:59:07 +08:00
2009-09-01 18:48:32 +08:00
inline void luminance ( float & ) const { }
inline void alpha ( float & ) const { }
inline void luminance_alpha ( float & l , float & a ) const { a * = l ; }
2005-02-02 06:36:05 +08:00
inline void rgb ( float & , float & , float & ) const { }
inline void rgba ( float & r , float & g , float & b , float & a ) const { float l = ( r + g + b ) * 0.3333333 ; a * = l ; }
} ;
2005-02-01 04:09:24 +08:00
2005-09-04 04:56:25 +08:00
struct ModulateAlphaByColourOperator
2005-02-02 06:36:05 +08:00
{
2005-09-04 04:56:25 +08:00
ModulateAlphaByColourOperator ( const osg : : Vec4 & colour ) : _colour ( colour ) { _lum = _colour . length ( ) ; }
2009-09-01 18:48:32 +08:00
2005-02-02 06:36:05 +08:00
osg : : Vec4 _colour ;
float _lum ;
2009-09-01 18:48:32 +08:00
inline void luminance ( float & ) const { }
inline void alpha ( float & ) const { }
inline void luminance_alpha ( float & l , float & a ) const { a * = l * _lum ; }
2005-02-02 06:36:05 +08:00
inline void rgb ( float & , float & , float & ) const { }
2005-09-04 04:56:25 +08:00
inline void rgba ( float & r , float & g , float & b , float & a ) const { a = ( r * _colour . r ( ) + g * _colour . g ( ) + b * _colour . b ( ) + a * _colour . a ( ) ) ; }
2005-02-02 06:36:05 +08:00
} ;
struct ReplaceAlphaWithLuminanceOperator
{
ReplaceAlphaWithLuminanceOperator ( ) { }
2009-09-01 18:48:32 +08:00
inline void luminance ( float & ) const { }
inline void alpha ( float & ) const { }
inline void luminance_alpha ( float & l , float & a ) const { a = l ; }
2005-02-02 06:36:05 +08:00
inline void rgb ( float & , float & , float & ) const { }
inline void rgba ( float & r , float & g , float & b , float & a ) const { float l = ( r + g + b ) * 0.3333333 ; a = l ; }
} ;
2008-11-05 23:04:38 +08:00
osg : : Image * doColourSpaceConversion ( ColourSpaceOperation op , osg : : Image * image , osg : : Vec4 & colour )
2005-02-02 06:36:05 +08:00
{
switch ( op )
{
case ( MODULATE_ALPHA_BY_LUMINANCE ) :
2008-11-05 23:04:38 +08:00
{
2005-02-02 06:36:05 +08:00
std : : cout < < " doing conversion MODULATE_ALPHA_BY_LUMINANCE " < < std : : endl ;
2009-09-01 18:48:32 +08:00
osg : : modifyImage ( image , ModulateAlphaByLuminanceOperator ( ) ) ;
2008-11-05 23:04:38 +08:00
return image ;
}
2005-02-02 06:36:05 +08:00
case ( MODULATE_ALPHA_BY_COLOUR ) :
2008-11-05 23:04:38 +08:00
{
2005-02-02 06:36:05 +08:00
std : : cout < < " doing conversion MODULATE_ALPHA_BY_COLOUR " < < std : : endl ;
2009-09-01 18:48:32 +08:00
osg : : modifyImage ( image , ModulateAlphaByColourOperator ( colour ) ) ;
2008-11-05 23:04:38 +08:00
return image ;
}
2009-08-19 23:36:46 +08:00
case ( REPLACE_ALPHA_WITH_LUMINANCE ) :
2008-11-05 23:04:38 +08:00
{
2009-08-19 23:36:46 +08:00
std : : cout < < " doing conversion REPLACE_ALPHA_WITH_LUMINANCE " < < std : : endl ;
2009-09-01 18:48:32 +08:00
osg : : modifyImage ( image , ReplaceAlphaWithLuminanceOperator ( ) ) ;
2008-11-05 23:04:38 +08:00
return image ;
}
case ( REPLACE_RGB_WITH_LUMINANCE ) :
{
2009-08-19 23:36:46 +08:00
std : : cout < < " doing conversion REPLACE_ALPHA_WITH_LUMINANCE " < < std : : endl ;
2008-11-05 23:04:38 +08:00
osg : : Image * newImage = new osg : : Image ;
newImage - > allocateImage ( image - > s ( ) , image - > t ( ) , image - > r ( ) , GL_LUMINANCE , image - > getDataType ( ) ) ;
2009-01-09 23:19:25 +08:00
osg : : copyImage ( image , 0 , 0 , 0 , image - > s ( ) , image - > t ( ) , image - > r ( ) ,
2009-09-01 18:48:32 +08:00
newImage , 0 , 0 , 0 , false ) ;
2008-11-05 23:04:38 +08:00
return newImage ;
}
2005-02-02 06:36:05 +08:00
default :
2008-11-05 23:04:38 +08:00
return image ;
2005-02-02 06:36:05 +08:00
}
}
2008-09-12 23:41:30 +08:00
osg : : TransferFunction1D * readTransferFunctionFile ( const std : : string & filename )
{
std : : string foundFile = osgDB : : findDataFile ( filename ) ;
2009-09-01 18:48:32 +08:00
if ( foundFile . empty ( ) )
2008-09-12 23:41:30 +08:00
{
std : : cout < < " Error: could not find transfer function file : " < < filename < < std : : endl ;
return 0 ;
}
2009-09-01 18:48:32 +08:00
2008-09-12 23:41:30 +08:00
std : : cout < < " Reading transfer function " < < filename < < std : : endl ;
2009-02-02 22:43:27 +08:00
osg : : TransferFunction1D : : ColorMap colorMap ;
2008-11-07 23:08:08 +08:00
osgDB : : ifstream fin ( foundFile . c_str ( ) ) ;
2008-09-12 23:41:30 +08:00
while ( fin )
{
float value , red , green , blue , alpha ;
fin > > value > > red > > green > > blue > > alpha ;
2009-09-01 18:48:32 +08:00
if ( fin )
2008-09-12 23:41:30 +08:00
{
std : : cout < < " value = " < < value < < " ( " < < red < < " , " < < green < < " , " < < blue < < " , " < < alpha < < " ) " < < std : : endl ;
2009-02-02 22:43:27 +08:00
colorMap [ value ] = osg : : Vec4 ( red , green , blue , alpha ) ;
2008-09-12 23:41:30 +08:00
}
}
2009-09-01 18:48:32 +08:00
2009-02-02 22:43:27 +08:00
if ( colorMap . empty ( ) )
2008-09-12 23:41:30 +08:00
{
std : : cout < < " Error: No values read from transfer function file: " < < filename < < std : : endl ;
return 0 ;
}
2009-09-01 18:48:32 +08:00
2008-09-12 23:41:30 +08:00
osg : : TransferFunction1D * tf = new osg : : TransferFunction1D ;
2009-02-02 22:43:27 +08:00
tf - > assign ( colorMap ) ;
2009-09-01 18:48:32 +08:00
2008-09-12 23:41:30 +08:00
return tf ;
}
2008-08-25 19:37:53 +08:00
class TestSupportOperation : public osg : : GraphicsOperation
{
public :
TestSupportOperation ( ) :
osg : : GraphicsOperation ( " TestSupportOperation " , false ) ,
supported ( true ) ,
errorMessage ( ) ,
maximumTextureSize ( 256 ) { }
virtual void operator ( ) ( osg : : GraphicsContext * gc )
{
OpenThreads : : ScopedLock < OpenThreads : : Mutex > lock ( mutex ) ;
glGetIntegerv ( GL_MAX_3D_TEXTURE_SIZE , & maximumTextureSize ) ;
2009-09-01 18:48:32 +08:00
2008-08-25 19:37:53 +08:00
osg : : notify ( osg : : NOTICE ) < < " Max texture size= " < < maximumTextureSize < < std : : endl ;
}
2009-09-01 18:48:32 +08:00
2008-08-25 19:37:53 +08:00
OpenThreads : : Mutex mutex ;
bool supported ;
std : : string errorMessage ;
GLint maximumTextureSize ;
} ;
2009-07-03 02:50:45 +08:00
class DraggerVolumeTileCallback : public osgManipulator : : DraggerCallback
{
public :
DraggerVolumeTileCallback ( osgVolume : : VolumeTile * volume , osgVolume : : Locator * locator ) :
_volume ( volume ) ,
_locator ( locator ) { }
virtual bool receive ( const osgManipulator : : MotionCommand & command ) ;
osg : : observer_ptr < osgVolume : : VolumeTile > _volume ;
osg : : ref_ptr < osgVolume : : Locator > _locator ;
osg : : Matrix _startMotionMatrix ;
osg : : Matrix _localToWorld ;
osg : : Matrix _worldToLocal ;
} ;
bool DraggerVolumeTileCallback : : receive ( const osgManipulator : : MotionCommand & command )
{
if ( ! _locator ) return false ;
switch ( command . getStage ( ) )
{
case osgManipulator : : MotionCommand : : START :
{
// Save the current matrix
_startMotionMatrix = _locator - > getTransform ( ) ;
// Get the LocalToWorld and WorldToLocal matrix for this node.
osg : : NodePath nodePathToRoot ;
osgManipulator : : computeNodePathToRoot ( * _volume , nodePathToRoot ) ;
_localToWorld = _startMotionMatrix * osg : : computeLocalToWorld ( nodePathToRoot ) ;
_worldToLocal = osg : : Matrix : : inverse ( _localToWorld ) ;
return true ;
}
case osgManipulator : : MotionCommand : : MOVE :
{
// Transform the command's motion matrix into local motion matrix.
osg : : Matrix localMotionMatrix = _localToWorld * command . getWorldToLocal ( )
* command . getMotionMatrix ( )
* command . getLocalToWorld ( ) * _worldToLocal ;
// Transform by the localMotionMatrix
_locator - > setTransform ( localMotionMatrix * _startMotionMatrix ) ;
2008-08-25 19:37:53 +08:00
2009-07-03 02:50:45 +08:00
// osg::notify(osg::NOTICE)<<"New locator matrix "<<_locator->getTransform()<<std::endl;
return true ;
}
case osgManipulator : : MotionCommand : : FINISH :
{
return true ;
}
case osgManipulator : : MotionCommand : : NONE :
default :
return false ;
}
}
2008-08-25 19:37:53 +08:00
2005-02-02 06:36:05 +08:00
int main ( int argc , char * * argv )
{
2004-06-29 21:59:07 +08:00
// use an ArgumentParser object to manage the program arguments.
osg : : ArgumentParser arguments ( & argc , argv ) ;
2009-09-01 18:48:32 +08:00
2004-06-29 21:59:07 +08:00
// set up the usage document, in case we need to print out how to use this program.
arguments . getApplicationUsage ( ) - > setDescription ( arguments . getApplicationName ( ) + " is the example which demonstrates use of 3D textures. " ) ;
arguments . getApplicationUsage ( ) - > setCommandLineUsage ( arguments . getApplicationName ( ) + " [options] filename ... " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " -h or --help " , " Display this information " ) ;
2005-02-01 04:09:24 +08:00
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " -s <numSlices> " , " Number of slices to create. " ) ;
2006-07-18 23:11:41 +08:00
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --images [filenames] " , " Specify a stack of 2d images to build the 3d volume from. " ) ;
2008-09-28 23:16:13 +08:00
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --shader " , " Use OpenGL Shading Language. (default) " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --no-shader " , " Disable use of OpenGL Shading Language. " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --gpu-tf " , " Aply the transfer function on the GPU. (default) " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --cpu-tf " , " Apply the transfer function on the CPU. " ) ;
2008-08-18 23:08:04 +08:00
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --mip " , " Use Maximum Intensity Projection (MIP) filtering. " ) ;
2005-02-01 04:09:24 +08:00
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --xSize <size> " , " Relative width of rendered brick. " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --ySize <size> " , " Relative length of rendered brick. " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --zSize <size> " , " Relative height of rendered brick. " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --xMultiplier <multiplier> " , " Tex coord x mulitplier. " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --yMultiplier <multiplier> " , " Tex coord y mulitplier. " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --zMultiplier <multiplier> " , " Tex coord z mulitplier. " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --clip <ratio> " , " clip volume as a ratio, 0.0 clip all, 1.0 clip none. " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --maxTextureSize <size> " , " Set the texture maximum resolution in the s,t,r (x,y,z) dimensions. " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --s_maxTextureSize <size> " , " Set the texture maximum resolution in the s (x) dimension. " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --t_maxTextureSize <size> " , " Set the texture maximum resolution in the t (y) dimension. " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --r_maxTextureSize <size> " , " Set the texture maximum resolution in the r (z) dimension. " ) ;
2005-08-26 21:26:02 +08:00
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --compressed " , " Enable the usage of compressed textures. " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --compressed-arb " , " Enable the usage of OpenGL ARB compressed textures. " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --compressed-dxt1 " , " Enable the usage of S3TC DXT1 compressed textures. " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --compressed-dxt3 " , " Enable the usage of S3TC DXT3 compressed textures. " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --compressed-dxt5 " , " Enable the usage of S3TC DXT5 compressed textures. " ) ;
2008-11-05 23:59:48 +08:00
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --modulate-alpha-by-luminance " , " For each pixel multiply the alpha value by the luminance. " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --replace-alpha-with-luminance " , " For each pixel set the alpha value to the luminance. " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --replace-rgb-with-luminance " , " For each rgb pixel convert to the luminance. " ) ;
2005-08-26 21:26:02 +08:00
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --num-components <num> " , " Set the number of components to in he target image. " ) ;
2008-11-05 23:59:48 +08:00
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --no-rescale " , " Disable the rescaling of the pixel data to 0.0 to 1.0 range " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --rescale " , " Enable the rescale of the pixel data to 0.0 to 1.0 range (default). " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --shift-min-to-zero " , " Shift the pixel data so min value is 0.0. " ) ;
2009-02-11 02:51:43 +08:00
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --sequence-length <num> " , " Set the length of time that a sequence of images with run for. " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --sd <num> " , " Short hand for --sequence-length " ) ;
2005-02-01 04:09:24 +08:00
// arguments.getApplicationUsage()->addCommandLineOption("--raw <sizeX> <sizeY> <sizeZ> <numberBytesPerComponent> <numberOfComponents> <endian> <filename>","read a raw image data");
2004-06-29 21:59:07 +08:00
// construct the viewer.
2008-08-25 17:53:24 +08:00
osgViewer : : Viewer viewer ( arguments ) ;
2004-06-29 21:59:07 +08:00
2008-08-27 01:40:04 +08:00
// add the window size toggle handler
viewer . addEventHandler ( new osgViewer : : WindowSizeHandler ) ;
2009-09-01 18:48:32 +08:00
2008-09-29 18:56:42 +08:00
{
osg : : ref_ptr < osgGA : : KeySwitchMatrixManipulator > keyswitchManipulator = new osgGA : : KeySwitchMatrixManipulator ;
keyswitchManipulator - > addMatrixManipulator ( ' 1 ' , " Trackball " , new osgGA : : TrackballManipulator ( ) ) ;
2009-09-01 18:48:32 +08:00
2008-09-30 02:30:17 +08:00
osgGA : : FlightManipulator * flightManipulator = new osgGA : : FlightManipulator ( ) ;
flightManipulator - > setYawControlMode ( osgGA : : FlightManipulator : : NO_AUTOMATIC_YAW ) ;
keyswitchManipulator - > addMatrixManipulator ( ' 2 ' , " Flight " , flightManipulator ) ;
2008-09-29 18:56:42 +08:00
viewer . setCameraManipulator ( keyswitchManipulator . get ( ) ) ;
}
2008-08-27 01:40:04 +08:00
// add the stats handler
viewer . addEventHandler ( new osgViewer : : StatsHandler ) ;
2008-08-25 18:38:39 +08:00
viewer . getCamera ( ) - > setClearColor ( osg : : Vec4 ( 0.0f , 0.0f , 0.0f , 0.0f ) ) ;
2004-06-29 21:59:07 +08:00
// if user request help write it out to cout.
if ( arguments . read ( " -h " ) | | arguments . read ( " --help " ) )
{
arguments . getApplicationUsage ( ) - > write ( std : : cout ) ;
return 1 ;
}
std : : string outputFile ;
while ( arguments . read ( " -o " , outputFile ) ) { }
2008-09-12 23:41:30 +08:00
osg : : ref_ptr < osg : : TransferFunction1D > transferFunction ;
std : : string tranferFunctionFile ;
while ( arguments . read ( " --tf " , tranferFunctionFile ) )
{
transferFunction = readTransferFunctionFile ( tranferFunctionFile ) ;
}
2009-09-01 18:48:32 +08:00
2009-02-02 22:43:27 +08:00
while ( arguments . read ( " --test " ) )
{
transferFunction = new osg : : TransferFunction1D ;
transferFunction - > setColor ( 0.0 , osg : : Vec4 ( 1.0 , 0.0 , 0.0 , 0.0 ) ) ;
transferFunction - > setColor ( 0.5 , osg : : Vec4 ( 1.0 , 1.0 , 0.0 , 0.5 ) ) ;
transferFunction - > setColor ( 1.0 , osg : : Vec4 ( 0.0 , 0.0 , 1.0 , 1.0 ) ) ;
}
while ( arguments . read ( " --test2 " ) )
{
transferFunction = new osg : : TransferFunction1D ;
transferFunction - > setColor ( 0.0 , osg : : Vec4 ( 1.0 , 0.0 , 0.0 , 0.0 ) ) ;
transferFunction - > setColor ( 0.5 , osg : : Vec4 ( 1.0 , 1.0 , 0.0 , 0.5 ) ) ;
transferFunction - > setColor ( 1.0 , osg : : Vec4 ( 0.0 , 0.0 , 1.0 , 1.0 ) ) ;
transferFunction - > assign ( transferFunction - > getColorMap ( ) ) ;
}
2008-09-12 23:41:30 +08:00
2004-07-12 00:38:16 +08:00
unsigned int numSlices = 500 ;
while ( arguments . read ( " -s " , numSlices ) ) { }
2009-09-01 18:48:32 +08:00
2004-07-12 00:38:16 +08:00
float sliceEnd = 1.0f ;
while ( arguments . read ( " --clip " , sliceEnd ) ) { }
2004-09-03 23:42:43 +08:00
float alphaFunc = 0.02f ;
while ( arguments . read ( " --alphaFunc " , alphaFunc ) ) { }
2004-07-12 00:38:16 +08:00
2009-09-01 18:48:32 +08:00
2008-09-26 19:29:00 +08:00
ShadingModel shadingModel = Standard ;
while ( arguments . read ( " --mip " ) ) shadingModel = MaximumIntensityProjection ;
2009-01-21 01:41:45 +08:00
while ( arguments . read ( " --isosurface " ) ) shadingModel = Isosurface ;
while ( arguments . read ( " --light " ) ) shadingModel = Light ;
2004-07-12 00:38:16 +08:00
2009-02-19 22:24:10 +08:00
float xSize = 0.0f , ySize = 0.0f , zSize = 0.0f ;
2004-09-04 17:22:26 +08:00
while ( arguments . read ( " --xSize " , xSize ) ) { }
while ( arguments . read ( " --ySize " , ySize ) ) { }
while ( arguments . read ( " --zSize " , zSize ) ) { }
2008-08-25 19:37:53 +08:00
osg : : ref_ptr < TestSupportOperation > testSupportOperation = new TestSupportOperation ;
viewer . setRealizeOperation ( testSupportOperation . get ( ) ) ;
2009-09-01 18:48:32 +08:00
2008-08-25 19:37:53 +08:00
viewer . realize ( ) ;
int maximumTextureSize = testSupportOperation - > maximumTextureSize ;
2008-09-12 23:41:30 +08:00
int s_maximumTextureSize = maximumTextureSize ;
int t_maximumTextureSize = maximumTextureSize ;
int r_maximumTextureSize = maximumTextureSize ;
2004-09-04 17:22:26 +08:00
while ( arguments . read ( " --maxTextureSize " , maximumTextureSize ) )
{
s_maximumTextureSize = maximumTextureSize ;
t_maximumTextureSize = maximumTextureSize ;
r_maximumTextureSize = maximumTextureSize ;
}
while ( arguments . read ( " --s_maxTextureSize " , s_maximumTextureSize ) ) { }
while ( arguments . read ( " --t_maxTextureSize " , t_maximumTextureSize ) ) { }
while ( arguments . read ( " --r_maxTextureSize " , r_maximumTextureSize ) ) { }
2004-09-03 23:42:43 +08:00
2004-09-29 18:01:46 +08:00
osg : : Texture : : InternalFormatMode internalFormatMode = osg : : Texture : : USE_IMAGE_DATA_FORMAT ;
while ( arguments . read ( " --compressed " ) | | arguments . read ( " --compressed-arb " ) ) { internalFormatMode = osg : : Texture : : USE_ARB_COMPRESSION ; }
while ( arguments . read ( " --compressed-dxt1 " ) ) { internalFormatMode = osg : : Texture : : USE_S3TC_DXT1_COMPRESSION ; }
while ( arguments . read ( " --compressed-dxt3 " ) ) { internalFormatMode = osg : : Texture : : USE_S3TC_DXT3_COMPRESSION ; }
while ( arguments . read ( " --compressed-dxt5 " ) ) { internalFormatMode = osg : : Texture : : USE_S3TC_DXT5_COMPRESSION ; }
2009-09-01 18:48:32 +08:00
2005-02-02 06:36:05 +08:00
// set up colour space operation.
ColourSpaceOperation colourSpaceOperation = NO_COLOUR_SPACE_OPERATION ;
osg : : Vec4 colourModulate ( 0.25f , 0.25f , 0.25f , 0.25f ) ;
while ( arguments . read ( " --modulate-alpha-by-luminance " ) ) { colourSpaceOperation = MODULATE_ALPHA_BY_LUMINANCE ; }
while ( arguments . read ( " --modulate-alpha-by-colour " , colourModulate . x ( ) , colourModulate . y ( ) , colourModulate . z ( ) , colourModulate . w ( ) ) ) { colourSpaceOperation = MODULATE_ALPHA_BY_COLOUR ; }
2009-08-19 23:36:46 +08:00
while ( arguments . read ( " --replace-alpha-with-luminance " ) ) { colourSpaceOperation = REPLACE_ALPHA_WITH_LUMINANCE ; }
2008-11-05 23:04:38 +08:00
while ( arguments . read ( " --replace-rgb-with-luminance " ) ) { colourSpaceOperation = REPLACE_RGB_WITH_LUMINANCE ; }
2008-11-05 23:59:48 +08:00
enum RescaleOperation
{
NO_RESCALE ,
RESCALE_TO_ZERO_TO_ONE_RANGE ,
SHIFT_MIN_TO_ZERO
} ;
2009-09-01 18:48:32 +08:00
2008-11-05 23:59:48 +08:00
RescaleOperation rescaleOperation = RESCALE_TO_ZERO_TO_ONE_RANGE ;
while ( arguments . read ( " --no-rescale " ) ) rescaleOperation = NO_RESCALE ;
while ( arguments . read ( " --rescale " ) ) rescaleOperation = RESCALE_TO_ZERO_TO_ONE_RANGE ;
while ( arguments . read ( " --shift-min-to-zero " ) ) rescaleOperation = SHIFT_MIN_TO_ZERO ;
2009-09-01 18:48:32 +08:00
2008-09-12 23:41:30 +08:00
bool resizeToPowerOfTwo = false ;
2009-09-01 18:48:32 +08:00
unsigned int numComponentsDesired = 0 ;
2005-08-26 21:26:02 +08:00
while ( arguments . read ( " --num-components " , numComponentsDesired ) ) { }
2009-07-03 02:50:45 +08:00
bool useManipulator = false ;
while ( arguments . read ( " --manipulator " ) | | arguments . read ( " -m " ) ) { useManipulator = true ; }
2009-09-01 18:48:32 +08:00
bool useShader = true ;
2005-09-05 15:48:55 +08:00
while ( arguments . read ( " --shader " ) ) { useShader = true ; }
2009-01-16 19:27:20 +08:00
while ( arguments . read ( " --no-shader " ) ) { useShader = false ; }
2005-08-26 21:26:02 +08:00
2009-09-01 18:48:32 +08:00
bool gpuTransferFunction = true ;
2008-09-24 18:45:15 +08:00
while ( arguments . read ( " --gpu-tf " ) ) { gpuTransferFunction = true ; }
2008-09-28 23:16:13 +08:00
while ( arguments . read ( " --cpu-tf " ) ) { gpuTransferFunction = false ; }
2008-09-24 18:45:15 +08:00
2009-02-11 02:51:43 +08:00
double sequenceLength = 10.0 ;
2009-09-01 18:48:32 +08:00
while ( arguments . read ( " --sequence-duration " , sequenceLength ) | |
arguments . read ( " --sd " , sequenceLength ) ) { }
2009-02-11 02:51:43 +08:00
2008-09-29 18:56:42 +08:00
typedef std : : list < osg : : ref_ptr < osg : : Image > > Images ;
Images images ;
2008-09-23 01:24:26 +08:00
std : : string vh_filename ;
2009-09-01 18:48:32 +08:00
while ( arguments . read ( " --vh " , vh_filename ) )
2008-09-23 01:24:26 +08:00
{
std : : string raw_filename , transfer_filename ;
2009-09-01 18:48:32 +08:00
int xdim ( 0 ) , ydim ( 0 ) , zdim ( 0 ) ;
2008-09-23 01:24:26 +08:00
2008-11-07 23:08:08 +08:00
osgDB : : ifstream header ( vh_filename . c_str ( ) ) ;
2008-09-23 01:24:26 +08:00
if ( header )
{
header > > raw_filename > > transfer_filename > > xdim > > ydim > > zdim > > xSize > > ySize > > zSize ;
}
2009-09-01 18:48:32 +08:00
2008-09-23 01:24:26 +08:00
if ( xdim * ydim * zdim = = 0 )
{
std : : cout < < " Error in reading volume header " < < vh_filename < < std : : endl ;
return 1 ;
}
2009-09-01 18:48:32 +08:00
2008-09-23 01:24:26 +08:00
if ( ! raw_filename . empty ( ) )
{
2008-09-29 18:56:42 +08:00
images . push_back ( readRaw ( xdim , ydim , zdim , 1 , 1 , " little " , raw_filename ) ) ;
2008-09-23 01:24:26 +08:00
}
2009-09-01 18:48:32 +08:00
2008-09-23 01:24:26 +08:00
if ( ! transfer_filename . empty ( ) )
{
2008-11-07 23:08:08 +08:00
osgDB : : ifstream fin ( transfer_filename . c_str ( ) ) ;
2008-09-23 01:24:26 +08:00
if ( fin )
{
2009-02-02 22:43:27 +08:00
osg : : TransferFunction1D : : ColorMap colorMap ;
2008-09-23 01:24:26 +08:00
float value = 0.0 ;
2008-09-24 18:20:23 +08:00
while ( fin & & value < = 1.0 )
2008-09-23 01:24:26 +08:00
{
float red , green , blue , alpha ;
fin > > red > > green > > blue > > alpha ;
2009-09-01 18:48:32 +08:00
if ( fin )
2008-09-23 01:24:26 +08:00
{
2009-02-02 22:43:27 +08:00
colorMap [ value ] = osg : : Vec4 ( red / 255.0f , green / 255.0f , blue / 255.0f , alpha / 255.0f ) ;
2008-09-24 18:20:23 +08:00
std : : cout < < " value = " < < value < < " ( " < < red < < " , " < < green < < " , " < < blue < < " , " < < alpha < < " ) " ;
2009-02-02 22:43:27 +08:00
std : : cout < < " ( " < < colorMap [ value ] < < " ) " < < std : : endl ;
2008-09-23 01:24:26 +08:00
}
value + = 1 / 255.0 ;
}
2009-02-02 22:43:27 +08:00
if ( colorMap . empty ( ) )
2008-09-23 01:24:26 +08:00
{
std : : cout < < " Error: No values read from transfer function file: " < < transfer_filename < < std : : endl ;
return 0 ;
}
transferFunction = new osg : : TransferFunction1D ;
2009-02-02 22:43:27 +08:00
transferFunction - > assign ( colorMap ) ;
2008-09-23 01:24:26 +08:00
}
}
}
2009-09-01 18:48:32 +08:00
2005-02-01 04:09:24 +08:00
int sizeX , sizeY , sizeZ , numberBytesPerComponent , numberOfComponents ;
std : : string endian , raw_filename ;
2009-09-01 18:48:32 +08:00
while ( arguments . read ( " --raw " , sizeX , sizeY , sizeZ , numberBytesPerComponent , numberOfComponents , endian , raw_filename ) )
2005-02-01 04:09:24 +08:00
{
2008-09-29 18:56:42 +08:00
images . push_back ( readRaw ( sizeX , sizeY , sizeZ , numberBytesPerComponent , numberOfComponents , endian , raw_filename ) ) ;
2005-02-01 04:09:24 +08:00
}
2008-11-04 20:57:30 +08:00
int images_pos = arguments . find ( " --images " ) ;
if ( images_pos > = 0 )
2004-06-29 21:59:07 +08:00
{
ImageList imageList ;
2008-11-04 20:57:30 +08:00
int pos = images_pos + 1 ;
for ( ; pos < arguments . argc ( ) & & ! arguments . isOption ( pos ) ; + + pos )
2004-06-29 21:59:07 +08:00
{
2010-11-01 19:06:12 +08:00
std : : string arg ( arguments [ pos ] ) ;
if ( arg . find ( ' * ' ) ! = std : : string : : npos )
2004-06-29 21:59:07 +08:00
{
2010-11-01 19:06:12 +08:00
osgDB : : DirectoryContents contents = osgDB : : expandWildcardsInFilename ( arg ) ;
for ( unsigned int i = 0 ; i < contents . size ( ) ; + + i )
{
osg : : Image * image = osgDB : : readImageFile ( contents [ i ] ) ;
if ( image )
{
imageList . push_back ( image ) ;
}
}
}
else
{
// not an option so assume string is a filename.
osg : : Image * image = osgDB : : readImageFile ( arguments [ pos ] ) ;
if ( image )
{
imageList . push_back ( image ) ;
}
2004-06-29 21:59:07 +08:00
}
}
2009-09-01 18:48:32 +08:00
2008-11-04 20:57:30 +08:00
arguments . remove ( images_pos , pos - images_pos ) ;
2009-09-01 18:48:32 +08:00
2004-06-29 21:59:07 +08:00
// pack the textures into a single texture.
ProcessRow processRow ;
2010-10-04 19:19:41 +08:00
osg : : Image * image = createTexture3D ( imageList , processRow , numComponentsDesired , s_maximumTextureSize , t_maximumTextureSize , r_maximumTextureSize , resizeToPowerOfTwo ) ;
if ( image ) images . push_back ( image ) ;
2004-06-29 21:59:07 +08:00
}
// any option left unread are converted into errors to write out later.
arguments . reportRemainingOptionsAsUnrecognized ( ) ;
2007-12-11 01:30:18 +08:00
// report any errors if they have occurred when parsing the program arguments.
2004-06-29 21:59:07 +08:00
if ( arguments . errors ( ) )
{
arguments . writeErrorMessages ( std : : cout ) ;
return 1 ;
}
2009-09-01 18:48:32 +08:00
2004-06-29 21:59:07 +08:00
2007-12-11 01:30:18 +08:00
// assume remaining arguments are file names of textures.
2008-09-29 18:56:42 +08:00
for ( int pos = 1 ; pos < arguments . argc ( ) ; + + pos )
2004-06-29 21:59:07 +08:00
{
if ( ! arguments . isOption ( pos ) )
{
2008-09-13 21:38:06 +08:00
std : : string filename = arguments [ pos ] ;
2008-09-16 03:59:12 +08:00
if ( osgDB : : getLowerCaseFileExtension ( filename ) = = " dicom " )
2008-09-13 21:38:06 +08:00
{
2008-10-02 23:45:08 +08:00
// not an option so assume string is a filename.
2010-10-04 19:19:41 +08:00
osg : : Image * image = osgDB : : readImageFile ( filename ) ;
if ( image )
2008-10-02 23:45:08 +08:00
{
images . push_back ( image ) ;
}
2008-09-13 21:38:06 +08:00
}
2008-09-16 03:59:12 +08:00
else
2008-09-13 21:38:06 +08:00
{
2008-09-16 03:59:12 +08:00
osgDB : : FileType fileType = osgDB : : fileType ( filename ) ;
if ( fileType = = osgDB : : FILE_NOT_FOUND )
2008-09-13 21:38:06 +08:00
{
2008-09-16 03:59:12 +08:00
filename = osgDB : : findDataFile ( filename ) ;
fileType = osgDB : : fileType ( filename ) ;
}
if ( fileType = = osgDB : : DIRECTORY )
{
2010-10-04 19:19:41 +08:00
osg : : Image * image = osgDB : : readImageFile ( filename + " .dicom " ) ;
if ( image ) images . push_back ( image ) ;
2008-09-16 03:59:12 +08:00
}
else if ( fileType = = osgDB : : REGULAR_FILE )
{
// not an option so assume string is a filename.
2010-10-04 19:19:41 +08:00
osg : : Image * image = osgDB : : readImageFile ( filename ) ;
if ( image ) images . push_back ( image ) ;
2008-09-16 03:59:12 +08:00
}
else
{
osg : : notify ( osg : : NOTICE ) < < " Error: could not find file: " < < filename < < std : : endl ;
return 1 ;
}
2009-09-01 18:48:32 +08:00
}
2004-06-29 21:59:07 +08:00
}
}
2009-09-01 18:48:32 +08:00
if ( images . empty ( ) )
2008-08-25 17:53:24 +08:00
{
std : : cout < < " No model loaded, please specify and volumetric image file on the command line. " < < std : : endl ;
return 1 ;
}
2008-09-16 23:32:23 +08:00
2008-09-29 18:56:42 +08:00
Images : : iterator sizeItr = images . begin ( ) ;
2009-02-19 22:24:10 +08:00
int image_s = ( * sizeItr ) - > s ( ) ;
int image_t = ( * sizeItr ) - > t ( ) ;
int image_r = ( * sizeItr ) - > r ( ) ;
2008-09-29 18:56:42 +08:00
+ + sizeItr ;
2008-09-30 02:30:17 +08:00
2008-09-29 18:56:42 +08:00
for ( ; sizeItr ! = images . end ( ) ; + + sizeItr )
{
2009-09-01 18:48:32 +08:00
if ( ( * sizeItr ) - > s ( ) ! = image_s | |
2009-02-19 22:24:10 +08:00
( * sizeItr ) - > t ( ) ! = image_t | |
( * sizeItr ) - > r ( ) ! = image_r )
2008-09-29 18:56:42 +08:00
{
std : : cout < < " Images in sequence are not of the same dimensions. " < < std : : endl ;
return 1 ;
}
}
2009-09-01 18:48:32 +08:00
osg : : ref_ptr < osgVolume : : ImageDetails > details = dynamic_cast < osgVolume : : ImageDetails * > ( images . front ( ) - > getUserData ( ) ) ;
osg : : ref_ptr < osg : : RefMatrix > matrix = details ? details - > getMatrix ( ) : dynamic_cast < osg : : RefMatrix * > ( images . front ( ) - > getUserData ( ) ) ;
2009-02-19 22:24:10 +08:00
if ( ! matrix )
{
if ( xSize = = 0.0 ) xSize = static_cast < float > ( image_s ) ;
if ( ySize = = 0.0 ) ySize = static_cast < float > ( image_t ) ;
if ( zSize = = 0.0 ) zSize = static_cast < float > ( image_r ) ;
2009-09-01 18:48:32 +08:00
2009-02-19 22:24:10 +08:00
matrix = new osg : : RefMatrix ( xSize , 0.0 , 0.0 , 0.0 ,
0.0 , ySize , 0.0 , 0.0 ,
0.0 , 0.0 , zSize , 0.0 ,
0.0 , 0.0 , 0.0 , 1.0 ) ;
}
2008-09-16 23:32:23 +08:00
2008-10-02 23:45:08 +08:00
osg : : Vec4 minValue ( FLT_MAX , FLT_MAX , FLT_MAX , FLT_MAX ) ;
osg : : Vec4 maxValue ( - FLT_MAX , - FLT_MAX , - FLT_MAX , - FLT_MAX ) ;
2008-09-29 18:56:42 +08:00
bool computeMinMax = false ;
for ( Images : : iterator itr = images . begin ( ) ;
itr ! = images . end ( ) ;
+ + itr )
{
2008-10-02 23:45:08 +08:00
osg : : Vec4 localMinValue , localMaxValue ;
2009-01-09 23:19:25 +08:00
if ( osg : : computeMinMax ( itr - > get ( ) , localMinValue , localMaxValue ) )
2008-09-30 02:30:17 +08:00
{
2008-10-02 23:45:08 +08:00
if ( localMinValue . r ( ) < minValue . r ( ) ) minValue . r ( ) = localMinValue . r ( ) ;
if ( localMinValue . g ( ) < minValue . g ( ) ) minValue . g ( ) = localMinValue . g ( ) ;
if ( localMinValue . b ( ) < minValue . b ( ) ) minValue . b ( ) = localMinValue . b ( ) ;
if ( localMinValue . a ( ) < minValue . a ( ) ) minValue . a ( ) = localMinValue . a ( ) ;
if ( localMaxValue . r ( ) > maxValue . r ( ) ) maxValue . r ( ) = localMaxValue . r ( ) ;
if ( localMaxValue . g ( ) > maxValue . g ( ) ) maxValue . g ( ) = localMaxValue . g ( ) ;
if ( localMaxValue . b ( ) > maxValue . b ( ) ) maxValue . b ( ) = localMaxValue . b ( ) ;
if ( localMaxValue . a ( ) > maxValue . a ( ) ) maxValue . a ( ) = localMaxValue . a ( ) ;
osg : : notify ( osg : : NOTICE ) < < " ( " < < localMinValue < < " ) ( " < < localMaxValue < < " ) " < < ( * itr ) - > getFileName ( ) < < std : : endl ;
computeMinMax = true ;
2008-09-30 02:30:17 +08:00
}
2008-09-29 18:56:42 +08:00
}
2009-09-01 18:48:32 +08:00
2008-09-29 18:56:42 +08:00
if ( computeMinMax )
2008-09-16 23:32:23 +08:00
{
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 ] ) ;
2009-09-01 18:48:32 +08:00
#if 0
2008-11-05 23:59:48 +08:00
switch ( rescaleOperation )
{
case ( NO_RESCALE ) :
break ;
case ( RESCALE_TO_ZERO_TO_ONE_RANGE ) :
{
float scale = 0.99f / ( maxComponent - minComponent ) ;
float offset = - minComponent * scale ;
for ( Images : : iterator itr = images . begin ( ) ;
itr ! = images . end ( ) ;
+ + itr )
2009-09-01 18:48:32 +08:00
{
osg : : offsetAndScaleImage ( itr - > get ( ) ,
2008-11-05 23:59:48 +08:00
osg : : Vec4 ( offset , offset , offset , offset ) ,
osg : : Vec4 ( scale , scale , scale , scale ) ) ;
}
break ;
}
case ( SHIFT_MIN_TO_ZERO ) :
{
float offset = - minComponent ;
for ( Images : : iterator itr = images . begin ( ) ;
itr ! = images . end ( ) ;
+ + itr )
2009-09-01 18:48:32 +08:00
{
osg : : offsetAndScaleImage ( itr - > get ( ) ,
2008-11-05 23:59:48 +08:00
osg : : Vec4 ( offset , offset , offset , offset ) ,
osg : : Vec4 ( 1.0f , 1.0f , 1.0f , 1.0f ) ) ;
}
break ;
}
} ;
2009-09-01 18:48:32 +08:00
# endif
2008-09-16 23:32:23 +08:00
}
2009-09-01 18:48:32 +08:00
2005-02-02 06:36:05 +08:00
if ( colourSpaceOperation ! = NO_COLOUR_SPACE_OPERATION )
{
2008-09-29 18:56:42 +08:00
for ( Images : : iterator itr = images . begin ( ) ;
itr ! = images . end ( ) ;
+ + itr )
2009-09-01 18:48:32 +08:00
{
2008-11-05 23:04:38 +08:00
( * itr ) = doColourSpaceConversion ( colourSpaceOperation , itr - > get ( ) , colourModulate ) ;
2008-09-29 18:56:42 +08:00
}
2005-02-02 06:36:05 +08:00
}
2009-09-01 18:48:32 +08:00
2008-09-24 18:45:15 +08:00
if ( ! gpuTransferFunction & & transferFunction . valid ( ) )
2008-09-12 23:41:30 +08:00
{
2008-09-29 18:56:42 +08:00
for ( Images : : iterator itr = images . begin ( ) ;
itr ! = images . end ( ) ;
+ + itr )
2009-09-01 18:48:32 +08:00
{
2009-01-17 01:59:38 +08:00
* itr = osgVolume : : applyTransferFunction ( itr - > get ( ) , transferFunction . get ( ) ) ;
2008-09-29 18:56:42 +08:00
}
2008-09-12 23:41:30 +08:00
}
2009-09-01 18:48:32 +08:00
2008-09-29 18:56:42 +08:00
osg : : ref_ptr < osg : : Image > image_3d = 0 ;
2004-09-29 18:01:46 +08:00
2008-09-29 18:56:42 +08:00
if ( images . size ( ) = = 1 )
{
osg : : notify ( osg : : NOTICE ) < < " Single image " < < images . size ( ) < < " volumes. " < < std : : endl ;
image_3d = images . front ( ) ;
}
else
{
osg : : notify ( osg : : NOTICE ) < < " Creating sequence of " < < images . size ( ) < < " volumes. " < < std : : endl ;
2009-09-01 18:48:32 +08:00
2008-09-29 18:56:42 +08:00
osg : : ref_ptr < osg : : ImageSequence > imageSequence = new osg : : ImageSequence ;
2009-02-11 02:51:43 +08:00
imageSequence - > setLength ( sequenceLength ) ;
2008-09-29 18:56:42 +08:00
image_3d = imageSequence . get ( ) ;
for ( Images : : iterator itr = images . begin ( ) ;
itr ! = images . end ( ) ;
+ + itr )
2009-09-01 18:48:32 +08:00
{
2008-09-29 18:56:42 +08:00
imageSequence - > addImage ( itr - > get ( ) ) ;
}
imageSequence - > play ( ) ;
}
2009-09-01 18:48:32 +08:00
2009-01-21 20:06:13 +08:00
osg : : ref_ptr < osgVolume : : Volume > volume = new osgVolume : : Volume ;
osg : : ref_ptr < osgVolume : : VolumeTile > tile = new osgVolume : : VolumeTile ;
2009-01-22 03:01:26 +08:00
volume - > addChild ( tile . get ( ) ) ;
2009-01-21 20:06:13 +08:00
2009-09-01 18:48:32 +08:00
osg : : ref_ptr < osgVolume : : ImageLayer > layer = new osgVolume : : ImageLayer ( image_3d . get ( ) ) ;
if ( details )
{
2009-09-03 21:40:50 +08:00
layer - > setTexelOffset ( details - > getTexelOffset ( ) ) ;
layer - > setTexelScale ( details - > getTexelScale ( ) ) ;
2009-09-01 18:48:32 +08:00
}
switch ( rescaleOperation )
{
case ( NO_RESCALE ) :
break ;
case ( RESCALE_TO_ZERO_TO_ONE_RANGE ) :
{
layer - > rescaleToZeroToOneRange ( ) ;
break ;
}
case ( SHIFT_MIN_TO_ZERO ) :
{
layer - > translateMinToZero ( ) ;
break ;
}
} ;
2009-01-21 20:06:13 +08:00
2009-07-03 02:50:45 +08:00
layer - > setLocator ( new osgVolume : : Locator ( * matrix ) ) ;
tile - > setLocator ( new osgVolume : : Locator ( * matrix ) ) ;
2009-01-09 23:19:25 +08:00
2009-01-21 20:06:13 +08:00
tile - > setLayer ( layer . get ( ) ) ;
2009-01-14 01:20:32 +08:00
2009-01-21 20:06:13 +08:00
tile - > setEventCallback ( new osgVolume : : PropertyAdjustmentCallback ( ) ) ;
2009-01-21 19:46:03 +08:00
2009-01-21 20:06:13 +08:00
if ( useShader )
{
2009-01-21 19:46:03 +08:00
osgVolume : : SwitchProperty * sp = new osgVolume : : SwitchProperty ;
sp - > setActiveProperty ( 0 ) ;
2009-01-21 20:06:13 +08:00
osgVolume : : AlphaFuncProperty * ap = new osgVolume : : AlphaFuncProperty ( alphaFunc ) ;
osgVolume : : SampleDensityProperty * sd = new osgVolume : : SampleDensityProperty ( 0.005 ) ;
osgVolume : : TransparencyProperty * tp = new osgVolume : : TransparencyProperty ( 1.0 ) ;
2009-02-01 05:45:47 +08:00
osgVolume : : TransferFunctionProperty * tfp = transferFunction . valid ( ) ? new osgVolume : : TransferFunctionProperty ( transferFunction . get ( ) ) : 0 ;
2009-01-21 20:06:13 +08:00
2009-01-21 19:46:03 +08:00
{
// Standard
osgVolume : : CompositeProperty * cp = new osgVolume : : CompositeProperty ;
2009-01-21 20:06:13 +08:00
cp - > addProperty ( ap ) ;
cp - > addProperty ( sd ) ;
cp - > addProperty ( tp ) ;
2009-01-29 17:24:45 +08:00
if ( tfp ) cp - > addProperty ( tfp ) ;
2009-01-21 19:46:03 +08:00
sp - > addProperty ( cp ) ;
}
{
// Light
osgVolume : : CompositeProperty * cp = new osgVolume : : CompositeProperty ;
2009-01-21 20:06:13 +08:00
cp - > addProperty ( ap ) ;
cp - > addProperty ( sd ) ;
cp - > addProperty ( tp ) ;
2009-01-21 19:46:03 +08:00
cp - > addProperty ( new osgVolume : : LightingProperty ) ;
2009-01-29 17:24:45 +08:00
if ( tfp ) cp - > addProperty ( tfp ) ;
2009-01-21 19:46:03 +08:00
sp - > addProperty ( cp ) ;
}
{
// Isosurface
osgVolume : : CompositeProperty * cp = new osgVolume : : CompositeProperty ;
2009-01-21 20:06:13 +08:00
cp - > addProperty ( sd ) ;
cp - > addProperty ( tp ) ;
2009-01-21 19:46:03 +08:00
cp - > addProperty ( new osgVolume : : IsoSurfaceProperty ( alphaFunc ) ) ;
2009-01-29 17:24:45 +08:00
if ( tfp ) cp - > addProperty ( tfp ) ;
2009-01-21 19:46:03 +08:00
sp - > addProperty ( cp ) ;
}
{
// MaximumIntensityProjection
osgVolume : : CompositeProperty * cp = new osgVolume : : CompositeProperty ;
2009-01-21 20:06:13 +08:00
cp - > addProperty ( ap ) ;
cp - > addProperty ( sd ) ;
cp - > addProperty ( tp ) ;
2009-01-21 19:46:03 +08:00
cp - > addProperty ( new osgVolume : : MaximumIntensityProjectionProperty ) ;
2009-01-29 17:24:45 +08:00
if ( tfp ) cp - > addProperty ( tfp ) ;
2009-01-21 19:46:03 +08:00
sp - > addProperty ( cp ) ;
}
2009-01-21 20:06:13 +08:00
2009-01-29 17:24:45 +08:00
switch ( shadingModel )
2009-01-21 20:06:13 +08:00
{
2009-01-29 17:24:45 +08:00
case ( Standard ) : sp - > setActiveProperty ( 0 ) ; break ;
case ( Light ) : sp - > setActiveProperty ( 1 ) ; break ;
case ( Isosurface ) : sp - > setActiveProperty ( 2 ) ; break ;
case ( MaximumIntensityProjection ) : sp - > setActiveProperty ( 3 ) ; break ;
2009-01-21 20:06:13 +08:00
}
2009-01-29 17:24:45 +08:00
layer - > addProperty ( sp ) ;
2009-01-21 20:06:13 +08:00
2009-01-21 22:27:58 +08:00
tile - > setVolumeTechnique ( new osgVolume : : RayTracedTechnique ) ;
2009-01-21 20:06:13 +08:00
}
else
{
layer - > addProperty ( new osgVolume : : AlphaFuncProperty ( alphaFunc ) ) ;
tile - > setVolumeTechnique ( new osgVolume : : FixedFunctionTechnique ) ;
2008-10-02 23:45:08 +08:00
}
2009-09-01 18:48:32 +08:00
2004-06-29 21:59:07 +08:00
if ( ! outputFile . empty ( ) )
2009-09-01 18:48:32 +08:00
{
2004-06-29 21:59:07 +08:00
std : : string ext = osgDB : : getFileExtension ( outputFile ) ;
std : : string name_no_ext = osgDB : : getNameLessExtension ( outputFile ) ;
if ( ext = = " osg " )
{
2004-09-06 22:58:29 +08:00
if ( image_3d . valid ( ) )
{
2009-09-01 18:48:32 +08:00
image_3d - > setFileName ( name_no_ext + " .dds " ) ;
2004-09-06 22:58:29 +08:00
osgDB : : writeImageFile ( * image_3d , image_3d - > getFileName ( ) ) ;
}
2009-01-21 20:06:13 +08:00
osgDB : : writeNodeFile ( * volume , outputFile ) ;
2004-06-29 21:59:07 +08:00
}
else if ( ext = = " ive " )
{
2009-09-01 18:48:32 +08:00
osgDB : : writeNodeFile ( * volume , outputFile ) ;
2004-06-29 21:59:07 +08:00
}
else if ( ext = = " dds " )
{
2009-01-21 20:06:13 +08:00
osgDB : : writeImageFile ( * image_3d , outputFile ) ;
2004-06-29 21:59:07 +08:00
}
else
{
std : : cout < < " Extension not support for file output, not file written. " < < std : : endl ;
}
2009-09-01 18:48:32 +08:00
2004-06-29 22:58:24 +08:00
return 0 ;
2004-06-29 21:59:07 +08:00
}
2009-09-01 18:48:32 +08:00
if ( volume . valid ( ) )
2004-06-29 21:59:07 +08:00
{
2009-07-03 02:50:45 +08:00
osg : : ref_ptr < osg : : Node > loadedModel = volume . get ( ) ;
if ( useManipulator )
{
osg : : ref_ptr < osg : : Group > group = new osg : : Group ;
2009-07-03 13:54:27 +08:00
# if 1
osg : : ref_ptr < osgManipulator : : Dragger > dragger = new osgManipulator : : TabBoxDragger ;
# else
osg : : ref_ptr < osgManipulator : : Dragger > dragger = new osgManipulator : : TrackballDragger ( ) ;
# endif
2009-07-03 02:50:45 +08:00
dragger - > setupDefaultGeometry ( ) ;
dragger - > setHandleEvents ( true ) ;
2009-07-04 03:16:53 +08:00
dragger - > setActivationModKeyMask ( osgGA : : GUIEventAdapter : : MODKEY_SHIFT ) ;
2009-07-03 02:50:45 +08:00
dragger - > addDraggerCallback ( new DraggerVolumeTileCallback ( tile . get ( ) , tile - > getLocator ( ) ) ) ;
dragger - > setMatrix ( osg : : Matrix : : translate ( 0.5 , 0.5 , 0.5 ) * tile - > getLocator ( ) - > getTransform ( ) ) ;
group - > addChild ( dragger . get ( ) ) ;
//dragger->addChild(volume.get());
group - > addChild ( volume . get ( ) ) ;
loadedModel = group ;
}
2004-06-29 21:59:07 +08:00
// set the scene to render
2009-07-03 02:50:45 +08:00
viewer . setSceneData ( loadedModel . get ( ) ) ;
2009-09-01 18:48:32 +08:00
2007-01-11 23:19:59 +08:00
// the the viewers main frame loop
viewer . run ( ) ;
2009-09-01 18:48:32 +08:00
}
2004-06-29 21:59:07 +08:00
return 0 ;
2005-02-01 04:09:24 +08:00
2004-06-29 21:59:07 +08:00
}