Commit 3f9c8622 authored by Robert Frohl's avatar Robert Frohl
Browse files

[MERGE]

parents 79db3dd1 496be145
......@@ -28,6 +28,7 @@
#include <osg/Node>
#include <osg/StateAttribute>
#include <osg/StateSet>
#include <osg/Drawable>
/**
* This class is needed as OSG does not define a uniform callback type.
......@@ -147,5 +148,33 @@ public:
}
};
/**
* Drawables have their own callback type and do NOT provide a traverse method.
*/
template <>
class WGECallbackTraits< osg::Drawable >
{
public:
/**
* The real callback type. Some specific OSG classes have specific callbacks. Specialize this template in this case.
*/
typedef osg::Drawable::UpdateCallback CallbackType;
/**
* The type of the element used as parameter in the () operator.
*/
typedef osg::Drawable HandledType;
/**
* Call traversal method if existing for the specific callback type.
*/
static void traverse( CallbackType* /*inst*/, HandledType* /*handled*/, osg::NodeVisitor* /*nv*/ )
{
// no traverse allowed
}
};
#endif // WGECALLBACKTRAITS_H
......@@ -70,6 +70,15 @@ public:
*/
virtual void operator()( Type* handled, osg::NodeVisitor* nv );
/**
* This gets called by OSG every update cycle. It calls the specified functor.
* \note we provide several versions here as the OSG does not uniformly use operator().
*
* \param handled the osg node, stateset or whatever
* \param nv the node visitor
*/
virtual void update( osg::NodeVisitor* nv, Type* handled );
protected:
private:
......@@ -101,5 +110,11 @@ void WGEFunctorCallback< Type >::operator()( Type* handled, osg::NodeVisitor* nv
WGECallbackTraits< Type >::traverse( this, handled, nv );
}
template < typename Type >
void WGEFunctorCallback< Type >::update( osg::NodeVisitor* nv, Type* handled )
{
operator()( handled, nv );
}
#endif // WGEFUNCTORCALLBACK_H
......@@ -98,6 +98,11 @@ void WGEShader::applyDirect( osg::State& state ) // NOLINT <- ensure this matche
void WGEShader::deactivate( osg::ref_ptr< osg::Node > node )
{
if ( !node )
{
return;
}
// set the shader attribute
// NOTE: the attribute is protected to avoid father nodes overwriting it
osg::StateSet* rootState = node->getOrCreateStateSet();
......
......@@ -202,11 +202,11 @@ vec4 negative2positive( in float value )
vec4 zeroColor = vec4( 1.0, 1.0, 1.0, 1.0 );
vec4 negColor = vec4( 1.0, 1.0, 0.0, 1.0 );
vec4 posColor= vec4( 0.0, 1.0, 1.0, 1.0 );
if ( val < -0.5 )
if ( val < 0.0 )
{
return ( zeroColor + negColor * val );
}
else if ( val > 0.5 )
else if ( val >= 0.0 )
{
return ( zeroColor - posColor * val );
}
......@@ -421,5 +421,61 @@ void colorMap( inout vec3 col, in float value, int cmap )
}
}
/**
* This method applies a colormap to the specified value an mixes it with the specified color. It uses the proper colormap and is able to unscale
* values if needed.
*
* \param color this color gets mixed using alpha value with the new colormap color
* \param value the value to map
* \param minV the minimum of the original value
* \param scaleV the scaler used to downscale the original value to [0-1]
* \param thresholdV a threshold in original space (you need to downscale it to [0-1] if you want to use it to scaled values.
* \param alpha the alpha blending value
* \param colormap the colormap index to use
*/
void colormap( inout vec4 color, in vec4 value, float minV, float scaleV, float thresholdV, float alpha, int colormap,
bool active )
{
// below threshold?
bool clip = ( value.r + value.g + value.b ) / 3.0 < ( ( minV + thresholdV ) / scaleV );
if ( clip )
{
return;
}
vec4 col;
if ( colormap == 0 )
{
col = value;
}
else if ( colormap == 1 )
{
col = rainbowColorMap( value.r );
}
else if ( colormap == 2 )
{
col = hotIronColorMap( value.r );
}
else if ( colormap == 3 )
{
col = negative2positive( value.r );
}
else if ( colormap == 4 )
{
col = atlasColorMap( value.r );
}
else if ( colormap == 5 )
{
col = blueGreenPurpleColorMap( value.r );
}
else if ( colormap == 6 )
{
col = vectorColorMap( value.rgb );
}
// finally mix colors according to alpha
color = mix( color, col, float( active ) * alpha );
}
#endif // WGECOLORMAPS_GLSL
......@@ -43,53 +43,14 @@
* \param scaleV the scaler used to downscale the original value to [0-1]
* \param thresholdV a threshold in original space (you need to downscale it to [0-1] if you want to use it to scaled values.
* \param alpha the alpha blending value
* \param colormap the colormap index to use
* \param cmap the colormap index to use
*/
void colormap( inout vec4 color, in sampler3D sampler, in vec3 coord, float minV, float scaleV, float thresholdV, float alpha, int colormap,
void colormap( inout vec4 color, in sampler3D sampler, in vec3 coord, float minV, float scaleV, float thresholdV, float alpha, int cmap,
bool active )
{
// get the value
vec4 value = texture3D( sampler, coord );
// below threshold?
bool clip = ( value.r + value.g + value.b ) / 3.0 < ( ( minV + thresholdV ) / scaleV );
if ( clip )
{
return;
}
vec4 col;
if ( colormap == 0 )
{
col = value;
}
else if ( colormap == 1 )
{
col = rainbowColorMap( value.r );
}
else if ( colormap == 2 )
{
col = hotIronColorMap( value.r );
}
else if ( colormap == 3 )
{
col = negative2positive( value.r );
}
else if ( colormap == 4 )
{
col = atlasColorMap( value.r );
}
else if ( colormap == 5 )
{
col = blueGreenPurpleColorMap( value.r );
}
else if ( colormap == 6 )
{
col = vectorColorMap( value.rgb );
}
// finally mix colors according to alpha
color = mix( color, col, float( active ) * alpha );
colormap( color, value, minV, scaleV, thresholdV, alpha, cmap, active );
}
/**
......
......@@ -103,7 +103,7 @@ WQtColormapper::~WQtColormapper()
m_sortConnection.disconnect();
}
WQtColormapper::WQtTextureListItem::WQtTextureListItem( const osg::ref_ptr< WGETexture3D > texture, QListWidget* parent ):
WQtColormapper::WQtTextureListItem::WQtTextureListItem( const osg::ref_ptr< WGETexture3D > texture, WQtColormapper* cmapper, QListWidget* parent ):
QListWidgetItem( QString::fromStdString( texture->name()->get() ), parent ),
m_texture( texture )
{
......@@ -113,10 +113,16 @@ WQtColormapper::WQtTextureListItem::WQtTextureListItem( const osg::ref_ptr< WGET
{
setText( QString::fromStdString( names.back() ) );
}
// we need to know the name of the texture
m_nameConnection = m_texture->name()->getUpdateCondition()->subscribeSignal(
boost::bind( &WQtColormapper::pushUpdateEvent, cmapper )
);
}
WQtColormapper::WQtTextureListItem::~WQtTextureListItem()
{
m_nameConnection.disconnect();
}
const osg::ref_ptr< WGETexture3D > WQtColormapper::WQtTextureListItem::getTexture() const
......@@ -160,7 +166,7 @@ void WQtColormapper::update()
m_textureListWidget->clear();
for ( WGEColormapping::TextureConstIterator iter = r->get().begin(); iter != r->get().end(); ++iter )
{
WQtTextureListItem* item = new WQtTextureListItem( *iter );
WQtTextureListItem* item = new WQtTextureListItem( *iter, this, m_textureListWidget );
m_textureListWidget->addItem( item ); // the list widget removes the item (and frees the reference to the texture pointer).
// is the item the texture that has been selected previously?
......
......@@ -137,8 +137,9 @@ private:
*
* \param texture the texture to handle with this item
* \param parent parent widget
* \param cmapper the colormapper widget managing updates for this item.
*/
WQtTextureListItem( const osg::ref_ptr< WGETexture3D > texture, QListWidget * parent = 0 );
WQtTextureListItem( const osg::ref_ptr< WGETexture3D > texture, WQtColormapper* cmapper, QListWidget* parent = 0 );
/**
* Destructor.
......@@ -157,6 +158,11 @@ private:
* The texture that gets handled
*/
const osg::ref_ptr< WGETexture3D > m_texture;
/**
* Connection for the texture's name property
*/
boost::signals2::connection m_nameConnection;
};
private slots:
......
......@@ -191,6 +191,8 @@ void WQtControlPanel::connectSlots()
connect( m_textureSorter, SIGNAL( textureSelectionChanged( boost::shared_ptr< WDataSet > ) ),
this, SLOT( selectDataModule( boost::shared_ptr< WDataSet > ) ) );
// }
connect( m_colormapper, SIGNAL( textureSelectionChanged( osg::ref_ptr< WGETexture3D > ) ),
this, SLOT( selectDataModule( osg::ref_ptr< WGETexture3D > ) ) );
connect( m_roiTreeWidget, SIGNAL( dragDrop() ), this, SLOT( handleDragDrop() ) );
}
......@@ -797,6 +799,12 @@ void WQtControlPanel::selectDataModule( boost::shared_ptr< WDataSet > dataSet )
selectTreeItem();
}
void WQtControlPanel::selectDataModule( osg::ref_ptr< WGETexture3D > texture )
{
m_tabWidget->clear();
buildPropTab( texture->getProperties(), texture->getInformationProperties() );
}
void WQtControlPanel::setNewActiveModule( boost::shared_ptr< WModule > module )
{
m_tabWidget->clear();
......
......@@ -351,6 +351,12 @@ private slots:
*/
void selectDataModule( boost::shared_ptr< WDataSet > dataSet );
/**
* Will be called to select the data module for the given texture.
* \param texture the texture currently selected.
*/
void selectDataModule( osg::ref_ptr< WGETexture3D > texture );
/**
* function that builds the property tab
*
......
......@@ -24,8 +24,18 @@
#include <string>
#include <boost/lexical_cast.hpp>
#include <osg/Projection>
#include <osg/Geode>
#include "../../dataHandler/WDataTexture3D_2.h"
#include "../../graphicsEngine/WGEColormapping.h"
#include "../../graphicsEngine/callbacks/WGENodeMaskCallback.h"
#include "../../graphicsEngine/callbacks/WGEFunctorCallback.h"
#include "../../graphicsEngine/WGEGeodeUtils.h"
#include "../../graphicsEngine/shaders/WGEShader.h"
#include "../../graphicsEngine/widgets/labeling/WGELabel.h"
#include "../../kernel/WKernel.h"
#include "WMColormapper.xpm"
......@@ -81,6 +91,8 @@ void WMColormapper::properties()
m_replace = m_properties->addProperty( "Keep position",
"If true, new texture on the input connector get placed in the list where the old one was.", true );
m_showColorbar = m_properties->addProperty( "Show Colorbar", "If true, a colorbar is shown for the current colormap.", false );
WModule::properties();
}
......@@ -91,6 +103,8 @@ void WMColormapper::moduleMain()
m_moduleState.add( m_input->getDataChangedCondition() );
m_moduleState.add( m_propCondition );
osg::ref_ptr< WGEShader > colormapShader = osg::ref_ptr< WGEShader > ( new WGEShader( "WMColormapper", m_localPath ) );
// signal ready state
ready();
......@@ -111,8 +125,83 @@ void WMColormapper::moduleMain()
// has the data changed?
if( m_input->handledUpdate() )
{
WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->remove( m_barProjection );
colormapShader->deactivate( m_colorBar );
boost::shared_ptr< WDataSetSingle > dataSet = m_input->getData();
// add a colorbar (HACK!)
if ( dataSet && dataSet->isTexture() )
{
// TODO(ebaum): this is not the best possible solution. Actually, its a hack.
// A nice solution would be some more abstract "widget" system
// create camera oriented 2d projection
m_barProjection = new osg::Projection();
m_barProjection->addUpdateCallback( new WGENodeMaskCallback( m_showColorbar ) );
m_barProjection->setMatrix( osg::Matrix::ortho2D( 0, 1.0, 0, 1.0 ) );
m_barProjection->getOrCreateStateSet()->setRenderBinDetails( 11, "RenderBin" );
m_barProjection->getOrCreateStateSet()->setDataVariance( osg::Object::DYNAMIC );
m_barProjection->getOrCreateStateSet()->setMode( GL_DEPTH_TEST, osg::StateAttribute::OFF );
m_barProjection->getOrCreateStateSet()->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
float borderWidth = 0.001;
// create a colorbar geode
m_colorBar = wge::genFinitePlane( osg::Vec3( 0.025, 0.1, 0.0 ), osg::Vec3( 0.025, 0.0, 0.0 ), osg::Vec3( 0.0, 0.8, 0.0 ) );
osg::ref_ptr< osg::Geode > colorBarBorder = wge::genFinitePlane( osg::Vec3( 0.025 - borderWidth, 0.1 - borderWidth, 0.0 ),
osg::Vec3( 0.025 + 2.0 * borderWidth, 0.0, 0.0 ),
osg::Vec3( 0.0, 0.8 + 2.0 * borderWidth, 0.0 ) );
m_colorBar->getOrCreateStateSet()->addUniform( new WGEPropertyUniform< WPropSelection >( "u_colormap",
dataSet->getTexture2()->colormap() ) );
colormapShader->apply( m_colorBar );
// add the label scale
osg::ref_ptr< WGELabel > topLabel = new WGELabel();
topLabel->setCharacterSize( 2 );
topLabel->setPosition( osg::Vec3( 0.055, 0.9, 0.0 ) );
topLabel->setText(
boost::lexical_cast< std::string >(
dataSet->getTexture2()->minimum()->get() + dataSet->getTexture2()->scale()->get()
)
);
topLabel->setCharacterSize( 0.02 );
topLabel->setAlignment( osgText::Text::LEFT_TOP );
osg::ref_ptr< WGELabel > bottomLabel = new WGELabel();
bottomLabel->setPosition( osg::Vec3( 0.055, 0.1, 0.0 ) );
bottomLabel->setText( boost::lexical_cast< std::string >( dataSet->getTexture2()->minimum()->get() ) );
bottomLabel->setCharacterSize( 0.02 );
osg::ref_ptr< WGELabel > nameLabel = new WGELabel();
nameLabel->setPosition( osg::Vec3( 0.015, 0.9, 0.0 ) );
nameLabel->setText( dataSet->getTexture2()->name()->get() );
nameLabel->setCharacterSize( 0.02 );
nameLabel->setLayout( osgText::TextBase::VERTICAL );
nameLabel->setAlignment( osgText::Text::BASE_LINE );
nameLabel->setUpdateCallback( new WGEFunctorCallback< osg::Drawable >(
boost::bind( &WMColormapper::updateColorbarName, this, _1 ) )
);
// the bar and the labels need to be added in an identity modelview matrix node
osg::ref_ptr< osg::MatrixTransform > matrix = new osg::MatrixTransform();
matrix->setMatrix( osg::Matrix::identity() );
matrix->setReferenceFrame( osg::Transform::ABSOLUTE_RF );
// this geode contains the labels
osg::ref_ptr< osg::Geode > labels = new osg::Geode();
labels->addDrawable( topLabel );
labels->addDrawable( bottomLabel );
labels->addDrawable( nameLabel );
// build pipeline
matrix->addChild( colorBarBorder );
matrix->addChild( m_colorBar );
matrix->addChild( labels );
m_barProjection->addChild( matrix );
// add
WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->insert( m_barProjection );
}
// replace texture instead of removing it?
if ( dataSet && dataSet->isTexture() && m_lastDataSet && m_replace->get( true ) )
{
......@@ -159,6 +248,9 @@ void WMColormapper::moduleMain()
WGEColormapping::deregisterTexture( m_lastDataSet->getTexture2() );
// NOTE: the props get removed automatically
}
// remove colorbar and its labels
WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->remove( m_barProjection );
}
void WMColormapper::activate()
......@@ -173,3 +265,11 @@ void WMColormapper::activate()
WModule::activate();
}
void WMColormapper::updateColorbarName( osg::Drawable* label )
{
if ( m_lastDataSet )
{
dynamic_cast< WGELabel* >( label )->setText( m_lastDataSet->getTexture2()->name()->get() );
}
}
......@@ -27,6 +27,8 @@
#include <string>
#include <osg/Projection>
#include "../../kernel/WModule.h"
#include "../../kernel/WModuleInputData.h"
#include "../../common/WPropertyVariable.h"
......@@ -116,6 +118,28 @@ private:
* If true, the new texture gets placed at the position of the old one in the texture sorter
*/
WPropBool m_replace;
/**
* If true, a colorbar is shown.
*/
WPropBool m_showColorbar;
/**
* The projection node for the colorbar and labels
*/
osg::ref_ptr< osg::Projection > m_barProjection;
/**
* The colorbar.
*/
osg::ref_ptr< osg::Geode > m_colorBar;
/**
* Updates the label for the dataset name
*
* \param label the label to update
*/
void updateColorbarName( osg::Drawable* label );
};
#endif // WMCOLORMAPPER_H
......
//---------------------------------------------------------------------------
//
// 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
#include "WGEColorMaps.glsl"
/////////////////////////////////////////////////////////////////////////////
// Varyings
/////////////////////////////////////////////////////////////////////////////
/**
* The value along the bar.
*/
varying float v_value;
/////////////////////////////////////////////////////////////////////////////
// Uniforms
/////////////////////////////////////////////////////////////////////////////
/**
* The colormap to show.
*/
uniform int u_colormap = 0;
/////////////////////////////////////////////////////////////////////////////
// Attributes
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// Variables
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// Functions
/////////////////////////////////////////////////////////////////////////////
/**
* Main entry point of the fragment shader.
*/
void main()
{
vec4 col = vec4( 0.0 );
colormap( col, vec4( v_value ), 0, 1.0, 0.0, 1.0, u_colormap, true );
gl_FragColor = col;
}
//---------------------------------------------------------------------------
//
// 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
/////////////////////////////////////////////////////////////////////////////
// Varyings
/////////////////////////////////////////////////////////////////////////////
/**
* The value along the bar.
*/
varying float v_value;
/////////////////////////////////////////////////////////////////////////////
// Uniforms
/////////////////////////////////////////////////////////////////////////////