Commit a6d9962a authored by Mathias Goldau's avatar Mathias Goldau

[CHANGE #373] Now we use a much more convenient update mechanism for slice positions

parent b755bfa0
......@@ -25,11 +25,11 @@
#include <string>
#include "core/common/WCondition.h"
#include "core/common/WPropTransfer.h"
#include "core/common/WItemSelectionItemTyped.h"
#include "core/graphicsEngine/WGEManagedGroupNode.h"
#include "core/kernel/WModuleInputData.h"
#include "WMAbstractSliceModule.h"
#include "WPropTransfer.h"
WMAbstractSliceModule::WMAbstractSliceModule()
: WModule(),
......@@ -43,7 +43,7 @@ WMAbstractSliceModule::~WMAbstractSliceModule()
void WMAbstractSliceModule::connectors()
{
m_sliceIC = WModuleInputData< WPropDoubleTransfer >::createAndAdd( shared_from_this(), "slice", "Slice and its position." );
m_posIC = WModuleInputData< WPositionTransfer >::createAndAdd( shared_from_this(), "positions", "Slice positions in x,y,z" );
WModule::connectors();
}
......
......@@ -27,7 +27,7 @@
#include <string>
#include "WPropTransfer.h"
#include "core/common/WPropTransfer.h"
#include "core/kernel/WModule.h"
// forward declarations to reduce compile dependencies
......@@ -118,7 +118,7 @@ protected:
/**
* Connector for external WPropDouble, so the slice type and position of this module can be controlled from another module.
*/
boost::shared_ptr< WModuleInputData< WPropDoubleTransfer > > m_sliceIC;
boost::shared_ptr< WModuleInputData< WPositionTransfer > > m_posIC;
/**
* The OSG root node for this module. All other geodes or OSG nodes will be attached on this single node.
......@@ -150,11 +150,6 @@ protected:
*/
boost::shared_ptr< WCondition > m_propCondition;
/**
* External property controlling linear translation of the given slice.
*/
WPropDouble m_externPropSlider;
private:
};
......
//---------------------------------------------------------------------------
//
// 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/>.
//
//---------------------------------------------------------------------------
#include "WPropTransfer.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/>.
//
//---------------------------------------------------------------------------
#ifndef WPROPTRANSFER_H
#define WPROPTRANSFER_H
#include <string>
#include "core/common/WProperties.h"
#include "core/common/WTransferable.h"
/**
* Encapulates a WPropertyVariable for transfering it (shared_ptr) over module connectors.
*/
template< class T >
class WPropTransfer: public WTransferable
{
public:
/**
* Alias for a boost::shared_ptr on this.
*/
typedef boost::shared_ptr< WPropTransfer< T > > SPtr;
/**
* Default constructor.
*/
explicit WPropTransfer();
/**
* Create a new Transferable containing a link to a property.
*
* \param property
*/
explicit WPropTransfer( T property );
/**
* Destructor.
*/
virtual ~WPropTransfer();
/**
* Gives back the name of this transferrable.
* \return the name
*/
virtual const std::string getName() const;
/**
* Gives back a description of this transferrable.
* \return the description
*/
virtual const std::string getDescription() const;
/**
* Returns a prototype instantiated with the true type of the deriving class.
*
* \return the prototype.
*/
static boost::shared_ptr< WPrototyped > getPrototype();
/**
* Sets a new property, beeing transfered via this transferable.
*
* \param property
*/
void setProperty( T property );
/**
* Retrieve the transfered property.
*
* \return Property.
*/
T getProperty();
private:
/**
* The prototype as singleton.
*/
static boost::shared_ptr< WPrototyped > m_prototype;
/**
* This is what is beeing shared with this transferable: a single property.
*/
T m_property;
};
template< class T >
WPropTransfer< T >::WPropTransfer( T property )
: m_property( property )
{
}
template< class T >
void WPropTransfer< T >::setProperty( T property )
{
m_property = property;
}
template< class T >
T WPropTransfer< T >::getProperty()
{
return m_property;
}
// prototype instance as singleton
template< class T >
boost::shared_ptr< WPrototyped > WPropTransfer< T >::m_prototype = boost::shared_ptr< WPrototyped >();
template< class T >
boost::shared_ptr< WPrototyped > WPropTransfer< T >::getPrototype()
{
if( !m_prototype )
{
m_prototype = boost::shared_ptr< WPrototyped >( new WPropTransfer< T >() );
}
return m_prototype;
}
template< class T >
const std::string WPropTransfer< T >::getName() const
{
return "Property transfer";
}
template< class T >
const std::string WPropTransfer< T >::getDescription() const
{
return "Transfers a property trough connectors. Be careful as multiple threads could use this!";
}
template< class T >
WPropTransfer< T >::WPropTransfer()
{
}
template< class T >
WPropTransfer< T >::~WPropTransfer()
{
}
typedef WPropTransfer< WPropDouble > WPropDoubleTransfer;
#endif // WPROPTRANSFER_H
......@@ -26,7 +26,6 @@
#include <core/kernel/WModule.h>
#include "aaSlices/WMAASlices.h"
#include "fiberStipples/WMFiberStipples.h"
#include "isoLines/WMIsoLines.h"
#include "WToolkit.h"
......@@ -37,6 +36,5 @@ extern "C" void WLoadModule( WModuleList& m ) // NOLINT
{
m.push_back( boost::shared_ptr< WModule >( new WMIsoLines ) );
m.push_back( boost::shared_ptr< WModule >( new WMFiberStipples ) );
m.push_back( boost::shared_ptr< WModule >( new WMAASlices ) );
}
//---------------------------------------------------------------------------
//
// 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/>.
//
//---------------------------------------------------------------------------
#include <cmath> // for logarithm function
#include <cstdlib>
#include <string>
#include <boost/array.hpp>
#include <osg/Geometry>
#include <osg/MatrixTransform>
#include "core/common/math/WMath.h"
#include "core/common/WItemSelectionItemTyped.h"
#include "core/dataHandler/WDataSetScalar.h"
#include "core/dataHandler/WDataSetVector.h"
#include "core/dataHandler/WGridRegular3D.h"
#include "core/graphicsEngine/callbacks/WGELinearTranslationCallback.h"
#include "core/graphicsEngine/callbacks/WGENodeMaskCallback.h"
#include "core/graphicsEngine/callbacks/WGEPropertyUniformCallback.h"
#include "core/graphicsEngine/shaders/WGEPropertyUniform.h"
#include "core/graphicsEngine/shaders/WGEShader.h"
#include "core/graphicsEngine/WGEColormapping.h"
#include "core/graphicsEngine/WGEGeodeUtils.h"
#include "core/graphicsEngine/WGEManagedGroupNode.h"
#include "core/graphicsEngine/WGraphicsEngine.h"
#include "core/kernel/WKernel.h"
#include "core/kernel/WModuleInputData.h"
#include "WMAASlices.h"
#include "WMAASlices.xpm"
WMAASlices::WMAASlices()
: WModule()
{
}
WMAASlices::~WMAASlices()
{
// Cleanup!
}
boost::shared_ptr< WModule > WMAASlices::factory() const
{
return boost::shared_ptr< WModule >( new WMAASlices() );
}
const char** WMAASlices::getXPMIcon() const
{
return WMAASlices_xpm;
}
const std::string WMAASlices::getName() const
{
return "Axis Aligned Planes";
}
const std::string WMAASlices::getDescription() const
{
return "Interactive axis aligned planes serving as \"selection-principle\" to other modules.";
}
void WMAASlices::connectors()
{
m_propOC[0] = WModuleOutputData< WPropDoubleTransfer >::createAndAdd( shared_from_this(), "propAxial", "Position slider of this slice." );
m_propOC[1] = WModuleOutputData< WPropDoubleTransfer >::createAndAdd( shared_from_this(), "propCoronal", "Position slider of this slice." );
m_propOC[2] = WModuleOutputData< WPropDoubleTransfer >::createAndAdd( shared_from_this(), "propSagittal", "Position slider of this slice." );
// call WModule's initialization
WModule::connectors();
}
void WMAASlices::properties()
{
m_pos[0] = m_properties->addProperty( "Axial Slice", "Slice position of axial slice", 0.0 );
m_pos[1] = m_properties->addProperty( "Coronal Slice", "Slice position of coronal slice", 0.0 );
m_pos[2] = m_properties->addProperty( "Sagittal Slice", "Slice position of sagittal slice", 0.0 );
m_showSlice[0] = m_properties->addProperty( "Show Axial", "Whether to show or hide this slice", true );
m_showSlice[1] = m_properties->addProperty( "Show Coronal", "Whether to show or hide this slice", true );
m_showSlice[2] = m_properties->addProperty( "Show Sagittal", "Whether to show or hide this slice", true );
// use classic RGB colors for the slices
m_color[0] = m_properties->addProperty( "Axial Color", "Color for this slice", WColor( 0.0, 0.0, 1.0, 0.1 ) );
m_color[1] = m_properties->addProperty( "Coronal Color", "Color for this slice", WColor( 1.0, 0.0, 0.0, 0.1 ) );
m_color[2] = m_properties->addProperty( "Sagittal Color", "Color for this slice", WColor( 0.0, 1.0, 0.0, 0.1 ) );
// call WModule's initialization
WModule::properties();
}
void WMAASlices::initOSG()
{
debugLog() << "Init OSG";
m_output->clear();
// grab the current bounding box
WBoundingBox bb = WGEColormapping::instance()->getBoundingBox();
WVector3d minV = bb.getMin();
WVector3d maxV = bb.getMax();
WVector3d sizes = ( maxV - minV );
WVector3d midBB = minV + ( sizes * 0.5 );
boost::array< osg::ref_ptr< osg::Node >, 3 > slices;
// NOTE: the indices are somehow swapped so we nee no cases inside the forloop below
boost::array< osg::Vec3, 3 > base = {{ osg::Vec3( 0.0, 0.0, 1.0 ), osg::Vec3( 0.0, 1.0, 0.0 ), osg::Vec3( 1.0, 0.0, 0.0 ) }}; // NOLINT curley braces
// we didn't put this into for loop as initialization becomes too bloated with if-else constructs
slices[0] = wge::genFinitePlane( minV, base[2] * sizes[0], base[1] * sizes[1] ); // axial
slices[1] = wge::genFinitePlane( minV, base[2] * sizes[0], base[0] * sizes[2] ); // coronal
slices[2] = wge::genFinitePlane( minV, base[1] * sizes[1], base[0] * sizes[2] ); // sagittal
boost::array< osg::ref_ptr< osg::MatrixTransform >, 3 > mT;
boost::array< osg::ref_ptr< osg::Uniform >, 3 > sliceUniforms;
for( int i = 0; i < 3; ++i )
{
m_pos[i]->setMin( minV[i] );
m_pos[i]->setMax( maxV[i] );
m_pos[i]->setHidden( false );
m_pos[i]->set( midBB[i] );
slices[i]->setCullingActive( false );
slices[i]->addUpdateCallback( new WGENodeMaskCallback( m_showSlice[i] ) );
sliceUniforms[i] = new osg::Uniform( "u_WorldTransform", osg::Matrix::identity() );
osg::ref_ptr< osg::Uniform > u_color = new WGEPropertyUniform< WPropColor >( "u_color", m_color[i] );
slices[i]->getOrCreateStateSet()->addUniform( sliceUniforms[i] );
slices[i]->getOrCreateStateSet()->addUniform( u_color );
mT[i] = new osg::MatrixTransform();
mT[i]->addUpdateCallback( new WGELinearTranslationCallback< WPropDouble >( base[i], m_pos[i], sliceUniforms[i] ) );
mT[i]->addChild( slices[i] );
m_output->insert( mT[i] );
}
m_output->getOrCreateStateSet()->setRenderingHint( osg::StateSet::TRANSPARENT_BIN );
m_output->getOrCreateStateSet()->setMode( GL_BLEND, osg::StateAttribute::ON );
m_output->getOrCreateStateSet()->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
m_output->dirtyBound();
}
void WMAASlices::moduleMain()
{
// get notified about data changes
m_moduleState.setResetable( true, true );
m_moduleState.add( WGEColormapping::instance()->getChangeCondition() );
ready();
// graphics setup
m_output = osg::ref_ptr< WGEManagedGroupNode >( new WGEManagedGroupNode( m_active ) );
WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->insert( m_output );
osg::ref_ptr< WGEShader > shader = new WGEShader( "WAASlices", m_localPath );
shader->apply( m_output ); // this automatically applies the shader
initOSG();
m_propOC[0]->updateData( WPropDoubleTransfer::SPtr( new WPropDoubleTransfer( m_pos[0] ) ) );
m_propOC[1]->updateData( WPropDoubleTransfer::SPtr( new WPropDoubleTransfer( m_pos[1] ) ) );
m_propOC[2]->updateData( WPropDoubleTransfer::SPtr( new WPropDoubleTransfer( m_pos[2] ) ) );
// main loop
while( !m_shutdownFlag() )
{
infoLog() << "Waitings ...";
m_moduleState.wait();
// woke up since the module is requested to finish?
if( m_shutdownFlag() )
{
break;
}
initOSG();
}
m_output->clear();
WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->remove( m_output );
}
//---------------------------------------------------------------------------
//
// 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/>.
//
//---------------------------------------------------------------------------
#ifndef WMAASLICES_H
#define WMAASLICES_H
#include <string>
#include "core/kernel/WModule.h"
#include "../WPropTransfer.h"
// forward declarations to reduce compile dependencies
template< class T > class WModuleInputData;
class WGEManagedGroupNode;
/**
* Interactive axis aligned planes (aka axial-, sagittal- or coronal slices).
* Serves as selection principle to other modules.
*
* \ingroup modules
*/
class WMAASlices: public WModule
{
public:
/**
* Default constructor.
*/
WMAASlices();
/**
* Destructor.
*/
virtual ~WMAASlices();
/**
* Gives back the name of this module.
* \return the module's name.
*/
virtual const std::string getName() const;
/**
* Gives back a description of this module.
* \return description to module.
*/
virtual const std::string getDescription() const;
/**
* Due to the prototype design pattern used to build modules, this method returns a new instance of this method. NOTE: it
* should never be initialized or modified in some other way. A simple new instance is required.
*
* \return the prototype used to create every module in OpenWalnut.
*/
virtual boost::shared_ptr< WModule > factory() const;
/**
* Get the icon for this module in XPM format.
* \return The icon.
*/
virtual const char** getXPMIcon() const;
protected:
/**
* Entry point after loading the module. Runs in separate thread.
*/
virtual void moduleMain();
/**
* Initialize the connectors this module is using.
*/
virtual void connectors();
/**
* Initialize the properties for this module.
*/
virtual void properties();
private:
/**
* Initialize OSG root node for this module. All other nodes from this module should be attached to this root node.
*/
void initOSG();
/**
* For each axis aligned slice an output with the property controlling the corresponding slice position.
*/
boost::array< boost::shared_ptr< WModuleOutputData< WPropDoubleTransfer > >, 3 > m_propOC;
/**
* Flags to trigger visibility of slices on or off.
*/
boost::array< WPropBool, 3 > m_showSlice;
/**
* Controlling the slice position on its axis.
*/
boost::array< WPropDouble, 3 > m_pos;
/**
* Color for each slice.
*/
boost::array< WPropColor, 3 > m_color;
/**
* The OSG root node for this module. All other geodes or OSG nodes will be attached on this single node.
*/
osg::ref_ptr< WGEManagedGroupNode > m_output;
};
#endif // WMAASLICES_H
/* XPM */
static const char * WMAASlices_xpm[] = {
"32 32 298 2",
" c None",
". c #FFFFFF",
"+ c #FFFEFE",
"@ c #FEFFFE",
"# c #FDFFFD",
"$ c #FFFEFF",
"% c #FFFDFD",
"& c #FFFCFC",
"* c #FFFBFB",
"= c #FEEAEA",
"- c #FFECEC",
"; c #E2FFE2",
"> c #E8FFE8",
", c #EFFEEF",
"' c #F6FFF6",
") c #FAFFFA",
"! c #FAFFFB",
"~ c #FBFFFB",
"{ c #FDFEFC",
"] c #FDFCFB",
"^ c #FDFBF9",
"/ c #FEF3F2",
"( c #FEDFDE",
"_ c #FFCACA",
": c #FFB6B6",
"< c #FFAEAE",
"[ c #FFD5D5",
"} c #B2FFB2",
"| c #AFFFAF",
"1 c #AEFFAF",
"2 c #B3FEB3",
"3 c #BDFCBA",
"4 c #C6FAC1",
"5 c #D1F7C9",
"6 c #E9E7D1",
"7 c #E3DABF",
"8 c #DEC8A7",
"9 c #E6B79E",