Commit ad23a446 authored by schurade's avatar schurade
Browse files

[Merge] with 1595469fc6f0461d0894935711922763164d8a72

parents 0aaddaad afe68e6e
......@@ -298,6 +298,15 @@ public:
return components[ components.size() / 2 ];
}
/**
* Changes the number of scalars held by this WValue.
* \param size The number of scalars stored in the WValue.
*/
void resize( size_t size )
{
m_components.resize( size );
}
protected:
private:
/**
......
......@@ -103,8 +103,12 @@ WColor WPropertyColorWidget::toWColor( QColor color )
void WPropertyColorWidget::buttonReleased()
{
QColor current = toQColor( m_colorProperty->get() );
current = QColorDialog::getColor( current, this );
#if QT_VERSION >= 0x040500
current = QColorDialog::getColor( current, this, QString( "Select Color" ), QColorDialog::ShowAlphaChannel );
#else
current = QColorDialog::getColor( current, this );
#endif
// convert it back to a WColor
invalidate( !m_colorProperty->set( toWColor( current ) ) ); // NOTE: set automatically checks the validity of the value
......
......@@ -282,7 +282,7 @@ void WModuleConnector::disconnect( boost::shared_ptr<WModuleConnector> con, bool
con->m_connected.erase( shared_from_this() );
lock.unlock();
// signal closed connection
// signal "closed connection"
signal_ConnectionClosed( shared_from_this(), con );
con->signal_ConnectionClosed( shared_from_this(), con );
}
......
......@@ -277,27 +277,27 @@ protected:
*/
virtual void notifyConnectionClosed( boost::shared_ptr<WModuleConnector> here, boost::shared_ptr<WModuleConnector> there );
private:
/**
* The connections name.
* Signal emitted whenever connection has been established.
*/
std::string m_name;
t_GenericSignalType signal_ConnectionEstablished;
/**
* The connections description.
* Signal emitted whenever connection has been closed.
*/
std::string m_description;
t_GenericSignalType signal_ConnectionClosed;
private:
/**
* Signal emitted whenever connection has been established.
* The connections name.
*/
t_GenericSignalType signal_ConnectionEstablished;
std::string m_name;
/**
* Signal emitted whenever connection has been closed.
* The connections description.
*/
t_GenericSignalType signal_ConnectionClosed;
std::string m_description;
};
#endif // WMODULECONNECTOR_H
......
......@@ -42,12 +42,17 @@ WModuleInputConnector::WModuleInputConnector( boost::shared_ptr< WModule > modul
// setup conditions
m_dataChangedCondition = boost::shared_ptr< WCondition >( new WCondition() );
// if connection is closed, also fire "data change"
signal_ConnectionClosed.connect( boost::bind( &WModuleInputConnector::setUpdated, this ) );
signal_ConnectionClosed.connect( boost::bind( &WCondition::notify, m_dataChangedCondition ) );
}
WModuleInputConnector::~WModuleInputConnector()
{
// cleanup
m_DataChangedConnection.disconnect();
signal_ConnectionClosed.disconnect_all_slots();
}
bool WModuleInputConnector::connectable( boost::shared_ptr<WModuleConnector> con )
......
......@@ -27,7 +27,6 @@
#include <utility>
#include "../../kernel/WKernel.h"
#include "../emptyIcon.xpm" // Please put a real icon here.
#include "../../dataHandler/WDataHandler.h"
#include "../../dataHandler/WDataTexture3D.h"
......
......@@ -85,12 +85,10 @@ const std::string WMDirectVolumeRendering::getDescription() const
void WMDirectVolumeRendering::connectors()
{
// DVR needs one input: the scalar dataset
m_input = boost::shared_ptr< WModuleInputData < WDataSetScalar > >(
new WModuleInputData< WDataSetScalar >( shared_from_this(), "in", "The scalar dataset shown using isosurface." )
);
m_input = WModuleInputData< WDataSetScalar >::createAndAdd( shared_from_this(), "in", "The scalar dataset." );
// As properties, every connector needs to be added to the list of connectors.
addConnector( m_input );
// Optional: the gradient field
m_gradients = WModuleInputData< WDataSetVector >::createAndAdd( shared_from_this(), "gradients", "The gradient field of the dataset to display" );
// call WModules initialization
WModule::connectors();
......@@ -102,9 +100,9 @@ void WMDirectVolumeRendering::properties()
m_propCondition = boost::shared_ptr< WCondition >( new WCondition() );
m_stepCount = m_properties->addProperty( "Step count", "The number of steps to walk along the ray during raycasting. A low value "
"may cause artifacts whilst a high value slows down rendering.", 250 );
"may cause artifacts whilst a high value slows down rendering.", 512 );
m_stepCount->setMin( 1 );
m_stepCount->setMax( 1000 );
m_stepCount->setMax( 5000 );
// illumination model
m_localIlluminationSelections = boost::shared_ptr< WItemSelection >( new WItemSelection() );
......@@ -138,6 +136,7 @@ void WMDirectVolumeRendering::moduleMain()
// let the main loop awake if the data changes or the properties changed.
m_moduleState.setResetable( true, true );
m_moduleState.add( m_input->getDataChangedCondition() );
m_moduleState.add( m_gradients->getDataChangedCondition() );
m_moduleState.add( m_propCondition );
// Signal ready state.
......@@ -164,7 +163,7 @@ void WMDirectVolumeRendering::moduleMain()
}
// was there an update?
bool dataUpdated = m_input->updated();
bool dataUpdated = m_input->updated() || m_gradients->updated();
boost::shared_ptr< WDataSetScalar > dataSet = m_input->getData();
bool dataValid = ( dataSet );
bool propUpdated = m_localIlluminationAlgo->changed() || m_tfLoaderEnabled || m_tfLoaderFile->changed() || m_tfLoaderTrigger->changed();
......@@ -204,7 +203,7 @@ void WMDirectVolumeRendering::moduleMain()
rootState->setMode( GL_BLEND, osg::StateAttribute::ON );
////////////////////////////////////////////////////////////////////////////////////////////////////
// setup defines (illumination)
// setup illumination
////////////////////////////////////////////////////////////////////////////////////////////////////
size_t localIlluminationAlgo = m_localIlluminationAlgo->get( true ).getItemIndexOfSelected( 0 );
......@@ -218,6 +217,19 @@ void WMDirectVolumeRendering::moduleMain()
break;
}
// if there is a gradient field available -> apply as texture too
boost::shared_ptr< WDataSetVector > gradients = m_gradients->getData();
if ( gradients )
{
debugLog() << "Uploading specified gradient field.";
// bind the texture to the node
rootState->setTextureAttributeAndModes( 1, gradients->getTexture()->getTexture(), osg::StateAttribute::ON );
rootState->addUniform( new osg::Uniform( "tex1", 1 ) );
m_shader->setDefine( "GRADIENTTEXTURE_SAMPLER", "tex1" );
m_shader->setDefine( "GRADIENTTEXTURE_ENABLED" );
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// load transfer function
////////////////////////////////////////////////////////////////////////////////////////////////////
......@@ -233,15 +245,16 @@ void WMDirectVolumeRendering::moduleMain()
tfTexture->setImage( tfImg );
// apply it
rootState->setTextureAttributeAndModes( 1, tfTexture, osg::StateAttribute::ON );
rootState->addUniform( new osg::Uniform( "tex1", 1 ) );
m_shader->setDefine( "TRANSFERFUNCTION_SAMPLER", "tex1" );
rootState->setTextureAttributeAndModes( 2, tfTexture, osg::StateAttribute::ON );
rootState->addUniform( new osg::Uniform( "tex2", 2 ) );
m_shader->setDefine( "TRANSFERFUNCTION_SAMPLER", "tex2" );
m_shader->setDefine( "TRANSFERFUNCTION_ENABLED" );
}
else
{
warnLog() << "Transfer function texture could not be loaded from " << m_tfLoaderFile->get( true ).file_string() << ".";
}
m_tfLoaderTrigger->get( true );
}
////////////////////////////////////////////////////////////////////////////////////////////////////
......@@ -262,7 +275,6 @@ void WMDirectVolumeRendering::moduleMain()
// build spatial search structure
////////////////////////////////////////////////////////////////////////////////////////////////////
// update node
debugLog() << "Adding new rendering.";
rootNode->clear();
......
......@@ -31,6 +31,8 @@
#include <osg/Uniform>
#include "../../graphicsEngine/WShader.h"
#include "../../dataHandler/WDataSetScalar.h"
#include "../../dataHandler/WDataSetVector.h"
#include "../../kernel/WModule.h"
#include "../../kernel/WModuleInputData.h"
#include "../../kernel/WModuleOutputData.h"
......@@ -108,6 +110,11 @@ private:
*/
boost::shared_ptr< WModuleInputData< WDataSetScalar > > m_input;
/**
* The gradient field input
*/
boost::shared_ptr< WModuleInputData< WDataSetVector > > m_gradients;
/**
* The number of steps to walk along the ray.
*/
......
......@@ -43,10 +43,7 @@
// texture containing the data
uniform sampler3D tex0;
uniform sampler1D TRANSFERFUNCTION_SAMPLER;
// The isovalue to use.
uniform float u_isovalue1 = 0.33;
uniform float u_isovalue2 = 0.80;
uniform sampler3D GRADIENTTEXTURE_SAMPLER;
/////////////////////////////////////////////////////////////////////////////
// Attributes
......@@ -99,6 +96,9 @@ vec3 findRayEnd( out float d )
*/
vec3 getGradient( in vec3 position )
{
#ifdef GRADIENTTEXTURE_ENABLED
return ( 2.0 * texture3D( GRADIENTTEXTURE_SAMPLER, position ).rgb ) + vec3( -1.0 );
#else
float s = 0.01;
float valueXP = texture3D( tex0, position + vec3( s, 0.0, 0.0 ) ).r;
float valueXM = texture3D( tex0, position - vec3( s, 0.0, 0.0 ) ).r;
......@@ -108,6 +108,7 @@ vec3 getGradient( in vec3 position )
float valueZM = texture3D( tex0, position - vec3( 0.0, 0.0, s ) ).r;
return vec3( valueXP - valueXM, valueYP - valueYM, valueZP - valueZM );
#endif
}
/**
......@@ -117,12 +118,12 @@ vec3 getGradient( in vec3 position )
*
* \return the color.
*/
vec4 transferFunction( in float value )
vec4 transferFunction( float value )
{
#ifdef TRANSFERFUNCTION_ENABLED
return texture1D( TRANSFERFUNCTION_SAMPLER, value );
#else
if ( isZero( value - 0.5, 0.1 ) ) // if not TF has been specified, at least show something
if ( isZero( value - 0.5, 0.01 ) ) // if not TF has been specified, at least show something
{
return vec4( 1.0, 0.0, 0.0, 0.1 );
}
......@@ -175,39 +176,33 @@ void main()
vec3 rayEnd = findRayEnd( totalDistance );
// walk along the ray
vec4 accumColor = vec4( vec3( 0.0 ), 1.0 ); // the composited color
float accumAlpha = 1.0; // accumulated transparency of the volume.
float depth = gl_FragCoord.z; // the depth of the last hit
float value; // the current value inside the data
float hit = 0.0; // this value will be != 0.0 if something has been hit
vec4 dst = vec4( 0.0 );
while ( currentDistance <= totalDistance )
{
// get current value
vec3 rayPoint = rayEnd - ( currentDistance * v_ray );
value = texture3D( tex0, rayPoint ).r;
// get current value, classify and illuminate
vec3 rayPoint = v_rayStart + ( currentDistance * v_ray );
vec4 src = localIllumination( rayPoint, transferFunction( texture3D( tex0, rayPoint ).r ) );
// go to next value
currentDistance += v_stepDistance;
// classify point in volume and evaluate local illumination model at this position
vec4 color = localIllumination( rayPoint, transferFunction( value ) );
// apply front-to-back compositing
dst = ( 1.0 - dst.a ) * src + dst;
// has there ever been something we hit?
hit = max( hit, color.a );
accumColor.rgba = mix( accumColor.rgba, color.rgba, color.a ); // compositing
accumAlpha *= ( 1.0 - color.a ); // compositing: keep track of final alpha value of the background
if ( dst.a >= 0.95 )
break;
}
// have we hit something which was classified not to be transparent?
// This is, visually, not needed but useful if volume rendere is used in conjunction with other geometry.
if ( isZero( hit ) )
{
discard;
}
// if ( isZero( dst.a ) )
// {
// discard;
// }
// set final color
accumColor.a = 1.0 - accumAlpha;
gl_FragColor = accumColor;
gl_FragDepth = depth;
float depth = gl_FragCoord.z;
gl_FragColor = dst;
gl_FragDepth = depth; // the depth of the last hit
}
......@@ -96,6 +96,11 @@ void WMFiberParameterColoring::properties()
{
m_propCondition = boost::shared_ptr< WCondition >( new WCondition() );
m_baseColor = m_properties->addProperty( "Base Color", "The base color. Some kind of color offset.", WColor( 1.0, 1.0, 1.0, 0.0 ),
m_propCondition );
m_scaleColor = m_properties->addProperty( "Scale Color", "The color which gets scaled with the calculated value and added to the base color.",
WColor( 0.0, 0.0, 0.0, 1.0 ), m_propCondition );
// call WModule's initialization
WModule::properties();
}
......@@ -147,7 +152,8 @@ void WMFiberParameterColoring::moduleMain()
bool dataUpdated = m_fiberInput->handledUpdate();
boost::shared_ptr< WDataSetFibers > dataSet = m_fiberInput->getData();
bool dataValid = ( dataSet );
if ( !dataValid || ( dataValid && !dataUpdated ) )
bool propUpdated = m_baseColor->changed() || m_scaleColor->changed();
if ( !dataValid || ( dataValid && !( dataUpdated || propUpdated ) ) )
{
continue;
}
......@@ -174,6 +180,16 @@ void WMFiberParameterColoring::moduleMain()
m_progress->addSubProgress( progress1 );
m_progress->addSubProgress( progress2 );
// for fastness:
double baseColorR = m_baseColor->get( true ).getRed();
double baseColorG = m_baseColor->get( true ).getGreen();
double baseColorB = m_baseColor->get( true ).getBlue();
double baseColorA = m_baseColor->get( true ).getAlpha();
double scaleColorR = m_scaleColor->get( true ).getRed();
double scaleColorG = m_scaleColor->get( true ).getGreen();
double scaleColorB = m_scaleColor->get( true ).getBlue();
double scaleColorA = m_scaleColor->get( true ).getAlpha();
// for each fiber:
debugLog() << "Iterating over all fibers.";
std::vector< double > maxSegLengths;
......@@ -235,10 +251,10 @@ void WMFiberParameterColoring::moduleMain()
double z = ( 2.0 / ( lenLast + segLen ) ) * ( current[2] - prev[2] );
double curvature = std::sqrt( x*x + y*y + z*z );
( *m_fibCurvatureColors )[ ( colorMode * k ) + cidx + 0 ] = 1.5 * curvature;
( *m_fibCurvatureColors )[ ( colorMode * k ) + cidx + 1 ] = 0.0;
( *m_fibCurvatureColors )[ ( colorMode * k ) + cidx + 2 ] = 0.0;
( *m_fibCurvatureColors )[ ( colorMode * k ) + cidx + 3 ] = 1.0;
( *m_fibCurvatureColors )[ ( colorMode * k ) + cidx + 0 ] = baseColorR + ( 1.5 * scaleColorR * curvature );
( *m_fibCurvatureColors )[ ( colorMode * k ) + cidx + 1 ] = baseColorG + ( 1.5 * scaleColorG * curvature );
( *m_fibCurvatureColors )[ ( colorMode * k ) + cidx + 2 ] = baseColorB + ( 1.5 * scaleColorB * curvature );
( *m_fibCurvatureColors )[ ( colorMode * k ) + cidx + 3 ] = baseColorA + ( 1.5 * scaleColorA * curvature );
( *m_fibLengthColors )[ ( colorMode * k ) + cidx + 0 ] = segLen;
( *m_fibLengthColors )[ ( colorMode * k ) + cidx + 1 ] = 0.0;
......@@ -273,10 +289,10 @@ void WMFiberParameterColoring::moduleMain()
for ( size_t k = 1; k < len - 1; ++k ) // len -1 because we interpret it as segments
{
double relSegLen = ( *m_fibLengthColors )[ ( colorMode * k ) + cidx + 0 ] / maxSegLengths[ fidx ];
( *m_fibLengthColors )[ ( colorMode * k ) + cidx + 0 ] = relSegLen;
( *m_fibLengthColors )[ ( colorMode * k ) + cidx + 1 ] = relSegLen;
( *m_fibLengthColors )[ ( colorMode * k ) + cidx + 2 ] = relSegLen;
( *m_fibLengthColors )[ ( colorMode * k ) + cidx + 3 ] = 1.0;
( *m_fibLengthColors )[ ( colorMode * k ) + cidx + 0 ] = baseColorR + ( scaleColorR * relSegLen );
( *m_fibLengthColors )[ ( colorMode * k ) + cidx + 1 ] = baseColorG + ( scaleColorG * relSegLen );
( *m_fibLengthColors )[ ( colorMode * k ) + cidx + 2 ] = baseColorB + ( scaleColorB * relSegLen );
( *m_fibLengthColors )[ ( colorMode * k ) + cidx + 3 ] = baseColorA + ( scaleColorA * relSegLen );
}
}
progress2->finish();
......
......@@ -120,6 +120,16 @@ private:
* The colors encoding the segment length
*/
WDataSetFibers::ColorArray m_fibLengthColors;
/**
* The offset color.
*/
WPropColor m_baseColor;
/**
* The color gets scaled by the calculated color (i.e. Curvature) and added to m_baseColor for each vertex.
*/
WPropColor m_scaleColor;
};
#endif // WMFIBERPARAMETERCOLORING_H
......
......@@ -259,7 +259,7 @@ void WMHistogramEqualization::moduleMain()
for ( size_t vi = 0; vi < valueSet->rawSize(); ++vi )
{
size_t idx = hist->getIndexForValue( valueSet->getScalarDouble( vi ) );
newData[ vi ] = static_cast< unsigned char >( idx / maxI * 255 );
newData[ vi ] = static_cast< unsigned char >( static_cast< double >( idx )/ static_cast< double >( maxI ) * 255.0 );
}
}
++*progress;
......
......@@ -103,9 +103,16 @@ void WMReadSphericalHarmonics::moduleMain()
}
std::string fileName = m_dataFile->get().string();
boost::shared_ptr< WProgress > progress;
progress = boost::shared_ptr< WProgress >( new WProgress( "Glyph Generation", 2 ) );
m_progress->addSubProgress( progress );
WReaderNIfTI niiLoader( fileName );
boost::shared_ptr< WDataSet > data;
data = niiLoader.load( W_DATASET_SPHERICALHARMONICS );
++*progress;
if( data )
{
m_data = boost::shared_dynamic_cast< WDataSetSphericalHarmonics >( data );
......@@ -116,5 +123,7 @@ void WMReadSphericalHarmonics::moduleMain()
}
}
m_readTriggerProp->set( WPVBaseTypes::PV_TRIGGER_READY, false );
progress->finish();
}
}
......@@ -171,7 +171,7 @@ inline T opTimes( T a, T b )
template< typename T >
inline T opDiv( T a, T b )
{
return a * b;
return a / b;
}
/**
......
......@@ -168,6 +168,10 @@ void WMTeemGlyphs::properties()
m_sliceIdProp->setMin( 0 );
m_sliceIdProp->setMax( 128 );
m_orderProp = m_properties->addProperty( "Order", "Will be rounded to the next even order", 4, m_recompute );
m_orderProp->setMin( 0 );
m_orderProp->setMax( 6 );
m_GFAThresholdProp = m_properties->addProperty( "GFA threshold", "Show only glyphs at voxels above the given generalized fractional"
" anisotropy (GFA) threshold"
" (if GFA data is present at input connector).",
......@@ -232,6 +236,18 @@ void WMTeemGlyphs::moduleMain()
break;
}
boost::shared_ptr< WDataSetScalar > gfa = m_inputGFA->getData();
if( gfa )
{
m_GFAThresholdProp->setMax( gfa->getMax() );
m_GFAThresholdProp->setMin( gfa->getMin() );
}
if( m_orderProp->get() % 2 != 0 )
{
m_orderProp->set( m_orderProp->get() + 1 );
}
renderSlice( m_sliceIdProp->get() );
}
......@@ -262,6 +278,7 @@ void WMTeemGlyphs::renderSlice( size_t sliceId )
boost::shared_dynamic_cast< WDataSetScalar >( m_inputGFA->getData() ),
m_GFAThresholdProp->get(),
sliceId,
m_orderProp->get(),
m_subdivisionLevelProp->get(),
m_moduloProp->get(),
sliceType,
......@@ -351,6 +368,7 @@ WMTeemGlyphs::GlyphGeneration::GlyphGeneration( boost::shared_ptr< WDataSetSpher
boost::shared_ptr< WDataSetScalar > dataGFA,
double thresholdGFA,
const size_t& sliceId,
const size_t& order,
const size_t& subdivisionLevel,
const size_t& modulo,
const size_t& sliceType,
......@@ -361,6 +379,7 @@ WMTeemGlyphs::GlyphGeneration::GlyphGeneration( boost::shared_ptr< WDataSetSpher
m_dataGFA( dataGFA ),
m_grid( boost::shared_dynamic_cast< WGridRegular3D >( dataSet->getGrid() ) ),
m_thresholdGFA( thresholdGFA ),
m_order( order ),
m_sliceType( sliceType ),
m_subdivisionLevel( subdivisionLevel ),
m_modulo( modulo ),
......@@ -434,12 +453,25 @@ void WMTeemGlyphs::GlyphGeneration::operator()( size_t id, size_t numThreads, WB
zSlice
};
WAssert( m_sphere->xyzwNum == m_sphere->normNum, "Wrong size of arrays." );
WAssert( m_sphere->xyzwNum == m_sphere->rgbaNum, "Wrong size of arrays." );
size_t nbVerts = m_sphere->xyzwNum;
const tijk_type *type = tijk_4o3d_sym;
const tijk_type *type = 0; // Initialized to quiet compiler
switch( m_order )
{
case 2:
type = tijk_2o3d_sym;
break;
case 4:
type = tijk_4o3d_sym;
break;
case 6:
type = tijk_6o3d_sym;
break;
default:
WAssert( false, "order above 6 not supported yet." );
}
// memory for the tensor and spherical harmonics data.
float* ten = new float[type->num];
......@@ -494,7 +526,7 @@ void WMTeemGlyphs::GlyphGeneration::operator()( size_t id, size_t numThreads, WB
//-------------------------------
// vertex indices
// We have to set them also if we do not darw the glyph becaus otherwise we would leave their
// We have to set them also if we do not draw the glyph because otherwise we would leave their
// to be zero. If many indices are zero, they block each other because of synchronized
// memory access to the same memory address.
for( unsigned int vertId = 0; vertId < localSphere->indxNum; ++vertId )
......@@ -509,16 +541,27 @@ void WMTeemGlyphs::GlyphGeneration::operator()( size_t id, size_t numThreads, WB
}
wmath::WValue< double > coeffs = m_dataSet->getSphericalHarmonicAt( posId ).getCoefficients();
WAssert( coeffs.size() == 15,
"This module can handle only 4th order spherical harmonics."
"Thus the input has to be 15 dimensional vectors." );
switch( m_order )
{
case 2:
coeffs.resize( 6 );
break;
case 4:
coeffs.resize( 15 );
break;
case 6:
coeffs.resize( 28 );
break;
default:
WAssert( false, "order above 6 not supported yet." );
}
for( size_t coeffId = 0; coeffId < 15; coeffId++ )
for( size_t coeffId = 0; coeffId < coeffs.size(); coeffId++ )
{
esh[coeffId] = coeffs[coeffId];
}
// convert even-order spherical harmonics to higher-order tensor
tijk_esh_to_3d_sym_f( ten, esh, 4 );
tijk_esh_to_3d_sym_f( ten, esh, m_order );
// create positive approximation of the tensor
tijk_refine_rankk_parm *parm = tijk_refine_rankk_parm_new();
......@@ -549,14 +592,19 @@ void WMTeemGlyphs::GlyphGeneration::operator()( size_t id, size_t numThreads, WB
// One can insert per-peak coloring here (see http://www.ci.uchicago.edu/~schultz/sphinx/home-glyph.html )
// -------------------------------------------------------------------------------------------------------