Commit c557c92f authored by Mathias Goldau's avatar Mathias Goldau
Browse files

[CHANGE] Many improvements over time. Outlining, Stratified and regular...

[CHANGE] Many improvements over time. Outlining, Stratified and regular samplers, shader improvements and shader debugging code,...
parent a950e3fd
......@@ -41,6 +41,7 @@
#include "lineGuidedSlice/WMLineGuidedSlice.h"
#include "matrixWriter/WMMatrixWriter.h"
#include "writeClusters/WMWriteClusters.h"
#include "bundleParamView/WMBundleParamView.h"
#include "WToolkit.h"
// This file's purpose is to provide a list of modules as entry point for OpenWalnut's module loader.
......@@ -62,5 +63,6 @@ extern "C" void WLoadModule( WModuleList& m ) // NOLINT
m.push_back( WModule::SPtr( new WMLoadClusters ) );
m.push_back( WModule::SPtr( new WMMatrixWriter ) );
m.push_back( WModule::SPtr( new WMWriteClusters ) );
m.push_back( WModule::SPtr( new WMBundleParamView ) );
}
......@@ -125,7 +125,39 @@ void WMFiberStipples::properties()
m_glyphSize->setMin( 0.01 );
m_glyphSize->setMax( 10.0 );
m_oldNew = m_properties->addProperty( "Old|New", "Old|New", true, m_propCondition );
m_regSamplesFactor = m_properties->addProperty( "Regular*#Samples", "Multiples of #Samples for regular sampling", 2.0, m_propCondition );
m_regSamplesFactor->setMin( 1.0 );
m_regSamplesFactor->setMax( 100 );
m_numSamples = m_properties->addProperty( "#Samples", "Number of Samples for uniform, stratified and regular sampling methods", 10000.0, m_propCondition );
m_numSamples->setMin( 100 );
m_numSamples->setMax( 100000 );
m_samplingMethods = boost::shared_ptr< WItemSelection >( new WItemSelection() );
m_samplingMethods->addItem( SamplingMethod::create( 0, "Poission", "Poission-Disk Sampling" ) );
m_samplingMethods->addItem( SamplingMethod::create( 1, "Stratified", "Stratified (Uniform-Cell) Sampling" ) );
m_samplingMethods->addItem( SamplingMethod::create( 2, "Uniform", "Uniform (Slice) Sampling" ) );
m_samplingMethods->addItem( SamplingMethod::create( 3, "Regular", "Regular Sampling" ) );
m_samplingSelection = m_properties->addProperty( "Sampling Method", "Which placement strategy. We suggest Poission-Disk!", m_samplingMethods->getSelector( 0 ), m_propCondition );
WPropertyHelper::PC_SELECTONLYONE::addTo( m_samplingSelection );
m_outline = m_properties->addProperty( "Outline", "Stipple Outline Y|N", true );
m_outlineWidth = m_properties->addProperty( "Outline Width", "Stipple Outline Width", 0.02 );
m_outlineWidth->setMin( 0.0 );
m_outlineWidth->setMax( 0.2 );
m_outlineSteps = m_properties->addProperty( "Outline Steps", "Stipple Outline Steps", 10 );
m_outlineSteps->setMin( 0 );
m_outlineSteps->setMax( 50 );
m_outlineDark = m_properties->addProperty( "Dark Outline", "Dark Stipple Outline or Bright", true );
m_outlineInOut = m_properties->addProperty( "In-Out Outline", "In/out-side of Stipple", true );
m_sampleRes = m_properties->addProperty( "PoissionRes", "Poission Sampling Resolution", 0.02, m_propCondition );
m_sampleRes->setMin( 0.0001 );
m_sampleRes->setMax( 0.2 );
// call WModule's initialization
WMAbstractSliceModule::properties();
......@@ -153,8 +185,8 @@ osg::ref_ptr< osg::Geode > WMFiberStipples::genScatteredDegeneratedQuads( const
// TODO(math): remove this ugly hack
double width = a.length();
double height = b.length();
double maxX = ( width >= height ? 1.0 : width / height );
double maxY = ( width >= height ? height / width : 1.0 );
double maxX = ( width <= height ? 1.0 : width / height );
double maxY = ( width <= height ? height / width : 1.0 );
double lambda0, lambda1;
for( size_t i = 0; i < glyphPositions.size(); ++i )
......@@ -261,12 +293,17 @@ void WMFiberStipples::initOSG( boost::shared_ptr< WDataSetScalar > probTract, co
wge::bindAsUniform( m_output, m_color, "u_color" );
wge::bindAsUniform( m_output, m_minRange, "u_minRange" );
wge::bindAsUniform( m_output, m_maxRange, "u_maxRange" );
wge::bindAsUniform( m_output, m_outline, "u_outline" );
wge::bindAsUniform( m_output, m_threshold, "u_threshold" );
wge::bindAsUniform( m_output, probTract->getMax(), "u_maxConnectivityScore" );
wge::bindAsUniform( m_output, numDensitySlices, "u_numDensitySlices" );
wge::bindAsUniform( m_output, m_glyphSize, "u_glyphSize" );
wge::bindAsUniform( m_output, m_glyphThickness, "u_glyphThickness" );
wge::bindAsUniform( m_output, m_colorThreshold, "u_colorThreshold" );
wge::bindAsUniform( m_output, m_outlineWidth, "u_outlineWidth" );
wge::bindAsUniform( m_output, m_outlineSteps, "u_outlineSteps" );
wge::bindAsUniform( m_output, m_outlineDark, "u_outlineDark" );
wge::bindAsUniform( m_output, m_outlineInOut, "u_outlineInOut" );
// each slice (containing scattered quads) is child of an transformation node
......@@ -277,14 +314,22 @@ void WMFiberStipples::initOSG( boost::shared_ptr< WDataSetScalar > probTract, co
for( size_t i = 0; i < numDensitySlices; ++i )
{
osg::ref_ptr< osg::Geode > slice;
if( !m_oldNew->get() )
{
slice = genScatteredDegeneratedQuads( WSampler2DUniform( 10000, 1.0, 1.0, DONT_CALL_SRAND ), minV, aVec, bVec, i );
}
else
// select sampling strategy
debugLog() << m_samplingSelection->get( true ).at( 0 );
switch( m_samplingSelection->get( true ).at( 0 )->getAs< SamplingMethod >()->getValue() )
{
slice = genScatteredDegeneratedQuads( m_samplers[i], minV, aVec, bVec, i );
case 0 : slice = genScatteredDegeneratedQuads( m_samplers[i], minV, aVec, bVec, i );
break;
case 1 : slice = genScatteredDegeneratedQuads( WSampler2DStratified( m_numSamples->get( true ), 1.0, 1.0, DONT_CALL_SRAND ), minV, aVec, bVec, i );
break;
case 2 : slice = genScatteredDegeneratedQuads( WSampler2DUniform( m_numSamples->get( true ), 1.0, 1.0, DONT_CALL_SRAND ), minV, aVec, bVec, i );
break;
case 3 : slice = genScatteredDegeneratedQuads( WSampler2DRegular( m_numSamples->get( true ) * m_regSamplesFactor->get( true ), 1.0, 1.0 ), minV, aVec, bVec, i );
break;
default : throw WException( "Invalid Sampling strategy selected" );
}
debugLog() << "Density slice " << i << ": " << slice->getDrawable(0)->asGeometry()->getVertexArray()->getNumElements() / 4 << " points";
slice->setCullingActive( false );
mT->addChild( slice );
......@@ -347,6 +392,7 @@ void WMFiberStipples::moduleMain()
// TODO(math): Remove this ugly hack as soon as possible
const size_t numDensitySlices = 20;
m_sampleRes->get( true ); // eat changes
WSampler2DPoisson sampler( 0.02 );
boost::shared_ptr< WProgress > splitProgress( new WProgress( "Split Poisson-Disk samplings hierachical", numDensitySlices ) );
m_progress->addSubProgress( splitProgress );
......@@ -387,6 +433,14 @@ void WMFiberStipples::moduleMain()
m_externPropSlider.reset();
infoLog() << "Removed external slice position control.";
}
if( m_sampleRes->changed() )
{
debugLog() << "New poission sampling resolution";
boost::filesystem::remove( "/tmp/klaus" );
boost::shared_ptr< WProgress > splitProgress( new WProgress( "Split Poisson-Disk samplings hierachical", numDensitySlices ) );
m_progress->addSubProgress( splitProgress );
m_samplers = splitSamplingPoisson( WSampler2DPoisson( m_sampleRes->get( true ) ), numDensitySlices, splitProgress );
}
if( m_externPropSlider && m_externPropSlider->changed() )
{
......
......@@ -157,6 +157,25 @@ private:
*/
WPropDouble m_glyphThickness;
WPropDouble m_regSamplesFactor;
WPropDouble m_numSamples;
WPropSelection m_samplingSelection;
WPropBool m_outline;
WPropDouble m_outlineWidth;
WPropInt m_outlineSteps;
WPropBool m_outlineDark;
WPropBool m_outlineInOut;
WPropDouble m_sampleRes;
boost::shared_ptr< WItemSelection > m_samplingMethods;
typedef WItemSelectionItemTyped< size_t > SamplingMethod;
/**
* For initial slice positioning we need to control if the module is in intial state or not.
*/
......@@ -164,7 +183,6 @@ private:
// TODO(math): Remove this ugly hack as soon as possible
std::vector< WSampler2D > m_samplers;
WPropBool m_oldNew;
};
#endif // WMFIBERSTIPPLES_H
......@@ -40,18 +40,53 @@ namespace
const double rndMax = RAND_MAX;
}
WSampler2DUniform::WSampler2DUniform( size_t numSamples, double width, double height, RandomInit init )
WSampler2DBase::WSampler2DBase( size_t numSamples, double width, double height, RandomInit init )
: WSampler2D(),
m_width( width ),
m_height( height )
{
reserve( numSamples );
if( init == CALL_SRAND )
{
srand( time( NULL ) );
}
}
WSampler2DRegular::WSampler2DRegular( size_t numSamples, double width, double height )
: WSampler2DBase( numSamples, width, height )
{
double maxX = std::sqrt( static_cast< double >( numSamples ) );
double maxY = maxX;
for( double col = 0.0; col < width; col += width / maxX )
{
for( double row = 0.0; row < height; row += height / maxY )
{
push_back( WVector2d( row, col ) );
}
}
}
WSampler2DStratified::WSampler2DStratified( size_t numSamples, double width, double height, RandomInit init )
: WSampler2DBase( numSamples, width, height, init )
{
double maxX = std::sqrt( static_cast< double >( numSamples ) );
double maxY = maxX;
for( double col = 0.0; col < width; col += width / maxX )
{
for( double row = 0.0; row < height; row += height / maxY )
{
double rnd1 = std::rand() / rndMax;
double rnd2 = std::rand() / rndMax;
push_back( WVector2d( row, col ) + WVector2d( rnd1 * height / maxY, rnd2 * width / maxX ) );
}
}
}
WSampler2DUniform::WSampler2DUniform( size_t numSamples, double width, double height, RandomInit init )
: WSampler2DBase( numSamples, width, height, init )
{
for( size_t i = 0; i < numSamples; ++i )
{
push_back( WVector2d( std::rand() / rndMax * m_width, std::rand() / rndMax * m_height ) );
......@@ -62,7 +97,7 @@ WSampler2DPoisson::WSampler2DPoisson( float radius )
: WSampler2D(),
m_radius( radius )
{
boost::shared_ptr< PDSampler > sampler( new BoundarySampler( 0.002, true ) );
boost::shared_ptr< PDSampler > sampler( new BoundarySampler( radius, true ) );
sampler->complete(); // generates PDSampling in [-1,1]^2 domain.
double x,y;
......
......@@ -65,10 +65,32 @@ enum RandomInit
DONT_CALL_SRAND
};
class WSampler2DBase : public WSampler2D
{
public:
/**
* Shortcut for boost shared pointers on that objects.
*/
typedef boost::shared_ptr< WSampler2DBase > SPtr;
WSampler2DBase( size_t numSamples, double width, double height, RandomInit init = DONT_CALL_SRAND );
protected:
/**
* X dimension.
*/
double m_width;
/**
* Y dimension.
*/
double m_height;
};
/**
* Generates uniform distributed random positions within the given a rectangular domain.
*/
class WSampler2DUniform : public WSampler2D
class WSampler2DUniform : public WSampler2DBase
{
public:
/**
......@@ -85,19 +107,47 @@ public:
* \param init Flag for calling srand or not
*/
explicit WSampler2DUniform( size_t numSamples, double width = 1.0, double height = 1.0, RandomInit init = CALL_SRAND );
};
protected:
class WSampler2DRegular : public WSampler2DBase
{
public:
/**
* X dimension.
* Shortcut for boost shared pointers on that objects.
*/
double m_width;
typedef boost::shared_ptr< WSampler2DRegular > SPtr;
/**
* Y dimension.
* Generates stratified sampled points distributed uniformly within each cell.
*
* \param numSamples How many samples.
* \param width X dimension
* \param height Y dimension
* \param init Flag for calling srand or not
*/
double m_height;
explicit WSampler2DRegular( size_t numSamples, double width = 1.0, double height = 1.0 );
};
class WSampler2DStratified : public WSampler2DBase
{
public:
/**
* Shortcut for boost shared pointers on that objects.
*/
typedef boost::shared_ptr< WSampler2DStratified > SPtr;
/**
* Generates stratified sampled points distributed uniformly within each cell.
*
* \param numSamples How many samples.
* \param width X dimension
* \param height Y dimension
* \param init Flag for calling srand or not
*/
explicit WSampler2DStratified( size_t numSamples, double width = 1.0, double height = 1.0, RandomInit init = CALL_SRAND );
};
/**
* Creates a Poisson Disk sampling in the [0,1]^2 domain.
* \note This sampling can be used as tile.
......
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut 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
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------
#version 120
/**
* These two uniforms are needed to transform the vectors out of their texture
* back to their original form as they are stored in RBGA (for example allowing
* only values between 0..1 for components but no negative ones).
*/
uniform float u_vectorsMin; uniform float u_vectorsScale;
/**
* The matrix describes the transformation of gl_Vertex to OpenWalnut Scene Space
*/
uniform mat4 u_WorldTransform;
/**
* Vector dataset as texture.
*/
uniform sampler3D u_vectorsSampler;
/**
* Probabilistic tract as texture.
*/
uniform sampler3D u_probTractSampler;
uniform sampler3D u_colSampler;
/**
* Number of voxels in X direction.
*/
uniform int u_probTractSizeX;
/**
* Number of voxels in Y direction.
*/
uniform int u_probTractSizeY;
/**
* Number of voxels in Z direction.
*/
uniform int u_probTractSizeZ;
// For correct transformation into texture space we also need the size of each voxel.
/**
* Voxel size in X direction.
*/
uniform float u_pixelSizeX;
/**
* Voxel size in Y direction.
*/
uniform float u_pixelSizeY;
/**
* Voxel size in Z direction.
*/
uniform float u_pixelSizeZ;
/**
* Used for scaling the focal points, as otherwise the the stipple endings may not fit inside quad.
*/
uniform float scale = 0.8;
/**
* Probabilities below this threshold are ignored and discarded.
*/
uniform float u_threshold;
/**
* Minimal density of the fiber stipples.
*/
uniform float u_minRange;
/**
* Maximal density of the fiber stipples.
*/
uniform float u_maxRange;
/**
* Middle point of the quad in texture coordinates, needed for scaling the
* projection of the principal diffusion direction to fit inside quad.
*/
uniform vec3 middlePoint_tex = vec3( 0.5, 0.5, 0.0 );
/**
* How much slices with random quads are used.
*/
uniform int u_numDensitySlices;
/**
* Scales the quad which is used later for the stipples.
*/
uniform float u_glyphSize;
/**
* Color of the fiber stipples. This will be further combined with tract probability.
*/
uniform vec4 u_color;
/**
* Scale the radius of the glyphs (aka stipples).
*/
uniform float u_glyphThickness;
uniform float u_outlineWidth;
uniform int u_outlineSteps;
uniform bool u_outlineDark;
/**
* All probabilities below this probability are highlighted to the color of this probability.
*/
uniform float u_colorThreshold;
uniform vec3 u_aVec;
uniform vec3 u_bVec;
uniform bool u_outline;
uniform bool u_outlineInOut;
......@@ -24,29 +24,11 @@
#version 120
/**
* First focal point, which is one of the endings of the projected diffusion direction.
*/
varying vec3 focalPoint1;
/**
* Second focal point, which is one of the endings of the projected diffusion direction.
*/
varying vec3 focalPoint2;
/**
* First focal point, scaled.
*/
varying vec3 scaledFocalPoint1;
/**
* Second focal poin, scaled.
*/
varying vec3 scaledFocalPoint2;
/**
* Scaled connectivity score; now between 0.0...1.0.
*/
varying float probability;
varying float v_probability;
// varying vec3 diff;
varying float col;
varying vec3 v_textPos;
......@@ -26,116 +26,9 @@
#include "WGETextureTools.glsl"
#include "WFiberStipples-varyings.glsl"
// #include "WGEColormapping-vertex.glsl"
#include "WFiberStipples-uniforms.glsl"
// #include "WGETransformationTools.glsl"
/**
* These two uniforms are needed to transform the vectors out of their texture
* back to their original form as they are stored in RBGA (for example allowing
* only values between 0..1 for components but no negative ones).
*/
uniform float u_vectorsMin; uniform float u_vectorsScale;
/**
* The matrix describes the transformation of gl_Vertex to OpenWalnut Scene Space
*/
uniform mat4 u_WorldTransform;
/**
* Vector dataset as texture.
*/
uniform sampler3D u_vectorsSampler;
/**
* Probabilistic tract as texture.
*/
uniform sampler3D u_probTractSampler;
uniform sampler3D u_colSampler;
/**
* Number of voxels in X direction.
*/
uniform int u_probTractSizeX;
/**
* Number of voxels in Y direction.
*/
uniform int u_probTractSizeY;
/**
* Number of voxels in Z direction.
*/
uniform int u_probTractSizeZ;
// For correct transformation into texture space we also need the size of each voxel.
/**
* Voxel size in X direction.
*/
uniform float u_pixelSizeX;
/**
* Voxel size in Y direction.
*/
uniform float u_pixelSizeY;
/**
* Voxel size in Z direction.
*/
uniform float u_pixelSizeZ;
/**
* First plane vector spanning the plane of the quad.
*/
uniform vec3 u_aVec;
/**
* Second plane vector spanning the plane of the quad.
*/
uniform vec3 u_bVec;
/**
* Used for scaling the focal points, as otherwise the the stipple endings may not fit inside quad.
*/
uniform float scale = 0.8;
/**
* Maximum connectivity score withing the probabilistic tract dataset. This is
* needed for scaling the connectivities between 0.0 and 1.0.
*/
uniform float u_maxConnectivityScore;
/**
* Probabilities below this threshold are ignored and discarded.
*/
uniform float u_threshold;
/**
* Minimal density of the fiber stipples.