Commit b215ac1a authored by cornimueller's avatar cornimueller
Browse files

[MERGE]

parents 86659703 8e03e544
......@@ -8,4 +8,5 @@ WALNUTPATH="$PWD/$BINDIR"
# go there and run walnut to ensure walnuts working directory is set correctly
cd $WALNUTPATH
echo "OpenWalnut built from: $(cat ./revision)"
./walnut-bin $@
......@@ -209,6 +209,14 @@ ELSE()
)
ENDIF()
#-------------------------------------------------------------------------------------------------------------
# Writes information about the revision of the current code to a file
ADD_CUSTOM_TARGET( identify
ALL
COMMAND hg identify -n -i -b -t > ${PROJECT_BINARY_DIR}/bin/revision
COMMENT "Write information about the revision of the current code to a file"
)
#-------------------------------------------------------------------------------------------------------------
# Prints the verbose output of the test runners, so you may identify the source of error early, if any
ADD_CUSTOM_TARGET( vtest
......
......@@ -26,6 +26,8 @@
#include <osg/Geometry>
#include <osg/Vec3>
#include <osg/Array>
#include <osg/ShapeDrawable>
#include <osg/MatrixTransform>
#include "../math/WPosition.h"
#include "WGEGeodeUtils.h"
......@@ -74,3 +76,109 @@ osg::ref_ptr< osg::Geode > wge::generateBoundingBoxGeode( const wmath::WPosition
return geode;
}
osg::ref_ptr< osg::Geometry > wge::createUnitCube( const WColor& color )
{
// create the unit cube manually as the ShapeDrawable and osg::Box does not provide 3D texture coordinates
osg::ref_ptr< osg::Geometry > cube = new osg::Geometry();
osg::ref_ptr< osg::Vec3Array > vertices = osg::ref_ptr< osg::Vec3Array >( new osg::Vec3Array );
osg::ref_ptr< osg::Vec3Array > normals = osg::ref_ptr< osg::Vec3Array >( new osg::Vec3Array );
osg::ref_ptr< osg::Vec4Array > colors = osg::ref_ptr< osg::Vec4Array >( new osg::Vec4Array );
// front face
vertices->push_back( osg::Vec3( 0.0, 0.0, 0.0 ) );
vertices->push_back( osg::Vec3( 1.0, 0.0, 0.0 ) );
vertices->push_back( osg::Vec3( 1.0, 1.0, 0.0 ) );
vertices->push_back( osg::Vec3( 0.0, 1.0, 0.0 ) );
normals->push_back( osg::Vec3( 0.0, 0.0, -1.0 ) );
// back face
vertices->push_back( osg::Vec3( 0.0, 0.0, 1.0 ) );
vertices->push_back( osg::Vec3( 1.0, 0.0, 1.0 ) );
vertices->push_back( osg::Vec3( 1.0, 1.0, 1.0 ) );
vertices->push_back( osg::Vec3( 0.0, 1.0, 1.0 ) );
normals->push_back( osg::Vec3( 0.0, 0.0, 1.0 ) );
// left
vertices->push_back( osg::Vec3( 0.0, 0.0, 0.0 ) );
vertices->push_back( osg::Vec3( 0.0, 1.0, 0.0 ) );
vertices->push_back( osg::Vec3( 0.0, 1.0, 1.0 ) );
vertices->push_back( osg::Vec3( 0.0, 0.0, 1.0 ) );
normals->push_back( osg::Vec3( -1.0, 0.0, 0.0 ) );
// right
vertices->push_back( osg::Vec3( 1.0, 0.0, 0.0 ) );
vertices->push_back( osg::Vec3( 1.0, 1.0, 0.0 ) );
vertices->push_back( osg::Vec3( 1.0, 1.0, 1.0 ) );
vertices->push_back( osg::Vec3( 1.0, 0.0, 1.0 ) );
normals->push_back( osg::Vec3( 1.0, 0.0, 0.0 ) );
// bottom
vertices->push_back( osg::Vec3( 0.0, 0.0, 0.0 ) );
vertices->push_back( osg::Vec3( 1.0, 0.0, 0.0 ) );
vertices->push_back( osg::Vec3( 1.0, 0.0, 1.0 ) );
vertices->push_back( osg::Vec3( 0.0, 0.0, 1.0 ) );
normals->push_back( osg::Vec3( 0.0, -1.0, 0.0 ) );
// top
vertices->push_back( osg::Vec3( 0.0, 1.0, 0.0 ) );
vertices->push_back( osg::Vec3( 1.0, 1.0, 0.0 ) );
vertices->push_back( osg::Vec3( 1.0, 1.0, 1.0 ) );
vertices->push_back( osg::Vec3( 0.0, 1.0, 1.0 ) );
normals->push_back( osg::Vec3( 0.0, 1.0, 0.0 ) );
// set it up and set arrays
cube->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::QUADS, 0, vertices->size() ) );
cube->setVertexArray( vertices );
// set 3D texture coordinates here.
cube->setTexCoordArray( 0, vertices );
// set normals
cube->setNormalArray( normals );
cube->setNormalBinding( osg::Geometry::BIND_PER_PRIMITIVE );
// finally, the colors
colors->push_back( wge::osgColor( color ) );
cube->setColorArray( colors );
cube->setColorBinding( osg::Geometry::BIND_OVERALL );
return cube;
}
osg::ref_ptr< osg::Node > wge::generateSolidBoundingBoxNode( const wmath::WPosition& pos1, const wmath::WPosition& pos2, const WColor& color,
bool threeDTexCoords )
{
assert( pos1[0] <= pos2[0] && pos1[1] <= pos2[1] && pos1[2] <= pos2[2] && "pos1 doesn't seem to be the frontLowerLeft corner of the BB!" );
// create a uni cube
osg::ref_ptr< osg::Geode > cube = new osg::Geode();
if ( threeDTexCoords )
{
cube->addDrawable( createUnitCube( color ) );
}
else
{
osg::ref_ptr< osg::ShapeDrawable > cubeDrawable = new osg::ShapeDrawable( new osg::Box( osg::Vec3( 0.5, 0.5, 0.5 ), 1.0 ) );
cubeDrawable->setColor( wge::osgColor( color ) );
cube->addDrawable( cubeDrawable );
}
// transform the cube to match the bbox
osg::Matrixd transformM;
osg::Matrixd scaleM;
transformM.makeTranslate( wge::osgVec3( pos1 ) );
scaleM.makeScale( wge::osgVec3( pos2 - pos1 ) );
// apply transformation to bbox
osg::ref_ptr< osg::MatrixTransform > transform = new osg::MatrixTransform();
transform->setMatrix( transformM * scaleM );
transform->addChild( cube );
// we do not need light
osg::StateSet* state = cube->getOrCreateStateSet();
state->setMode( GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED );
return transform;
}
......@@ -43,6 +43,29 @@ namespace wge
*/
osg::ref_ptr< osg::Geode > generateBoundingBoxGeode( const wmath::WPosition& pos1, const wmath::WPosition& pos2, const WColor& color );
/**
* Generates an OSG node for the specified bounding box. It uses solid faces. This actually returns a MatrixTransform node and is especially
* useful for shader based raytracing.
*
* \param pos1 Front lower left corner
* \param pos2 Back upper right corner
* \param color The color in which the bounding box should be generated
* \param threeDTexCoords True if 3D texture coordinates should be created.
*
* \return The OSG node containing the 12 edges of the box.
*/
osg::ref_ptr< osg::Node > generateSolidBoundingBoxNode( const wmath::WPosition& pos1, const wmath::WPosition& pos2, const WColor& color,
bool threeDTexCoords = true );
/**
* Creates a osg::Geometry containing an unit cube, having 3D texture coordinates.
*
* \param color the color to set for all vertices
*
* \return the geometry
*/
osg::ref_ptr< osg::Geometry > createUnitCube( const WColor& color );
} // end of namespace wge
#endif // WGEGEODEUTILS_H
......@@ -117,6 +117,12 @@ bool WGEZoomTrackballManipulator::handle( const osgGA::GUIEventAdapter& ea, osgG
{
return zoom( ea, us );
}
// NOTE: we need to ignore the right mouse-button drag! This manipulates the underlying Trackball Manipulator while, at the same time, is
// used for moving ROIS! Zooming is done using Scroll Wheel or +/- keys.
else if ( ( ea.getEventType() == osgGA::GUIEventAdapter::DRAG ) && ( ea.getButtonMask() == osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON ) )
{
return true;
}
else
{
return TrackballManipulator::handle( ea, us );
......
......@@ -243,7 +243,7 @@ void WQtGLWidget::keyPressEvent( QKeyEvent* event )
m_Viewer->keyEvent( WGEViewer::KEYPRESS, osgGA::GUIEventAdapter::KEY_Control_L );
break;
default :
std::cout << "Modifier key has no meaning yet." << std::endl;
break;
}
}
}
......
......@@ -78,12 +78,15 @@ WPropertyDoubleWidget::WPropertyDoubleWidget( WPropDouble property, QGridLayout*
m_spin.setMinimum( min );
m_spin.setMaximum( max );
// set display precision
m_spin.setDecimals( 5 );
// set the initial values
m_spin.setValue( m_doubleProperty->get() );
m_spin.setSingleStep( ( max - min ) / 100.0 );
// connect the modification signal of the edit and slider with our callback
connect( &m_spin, SIGNAL( valueChanged( double ) ), this, SLOT( spinChanged( double ) ) );
connect( &m_spin, SIGNAL( editingFinished() ), this, SLOT( spinChanged() ) );
}
WPropertyDoubleWidget::~WPropertyDoubleWidget()
......@@ -91,9 +94,9 @@ WPropertyDoubleWidget::~WPropertyDoubleWidget()
// cleanup
}
void WPropertyDoubleWidget::spinChanged( double value )
void WPropertyDoubleWidget::spinChanged()
{
// set to the property
invalidate( !m_doubleProperty->set( value ) );
invalidate( !m_doubleProperty->set( m_spin.value() ) );
}
......@@ -76,11 +76,9 @@ private:
public slots:
/**
* Called whenever the spin box changes
*
* \param value the new value
* Called whenever return is pressed or the spin box has a chaged value and looses focus
*/
void spinChanged( double value );
void spinChanged();
};
#endif // WPROPERTYDOUBLEWIDGET_H
......
......@@ -73,6 +73,11 @@ WQtDatasetBrowser::WQtDatasetBrowser( WMainWindow* parent )
m_downButton->setText( QString( "down" ) );
m_upButton = new QPushButton();
m_upButton->setText( QString( "up" ) );
// TODO(all): reenable these buttons if sorting works again
m_downButton->setDisabled( true );
m_upButton->setDisabled( true );
buttonLayout->addWidget( m_downButton );
buttonLayout->addWidget( m_upButton );
......
......@@ -324,42 +324,12 @@ boost::shared_ptr< WProgressCombiner > WModule::getRootProgressCombiner()
const char** WModule::getXPMIcon() const
{
// return empty 1x1 icon by default.
static const char * o_xpm[] =
{
"16 16 17 1",
"1 1 1 1",
" c None",
". c #B6B6B6",
"+ c #B0B0B0",
"@ c #B8B8B8",
"# c #A6A6A6",
"$ c #969696",
"% c #8C8C8C",
"& c #9F9F9F",
"* c #848484",
"= c #6F6F6F",
"- c #636363",
"; c #626262",
"> c #4A4A4A",
", c #3E3E3E",
"' c #2E2E2E",
") c #1F1F1F",
"! c #0D0D0D",
" ",
" ",
" .++. ",
" @#$%%$#@ ",
" @&*=--=*&@ ",
" #*;>,,>;*# ",
" .$=>'))'>=$. ",
" +%-,)!!),-%+ ",
" +%-,)!!),-%+ ",
" .$=>'))'>=$. ",
" #*;>,,>;*# ",
" @&*=--=*&@ ",
" @#$%%$#@ ",
" .++. ",
" ",
" "
" "
};
return o_xpm;
}
......@@ -374,6 +344,7 @@ void WModule::ready()
void WModule::threadMain()
{
#ifdef __linux__
// set the name of the thread. This name is shown by the "top", for example.
prctl( PR_SET_NAME, ( "walnut (" + getName() + ")" ).c_str() );
#endif
......
......@@ -44,7 +44,6 @@
#include "../modules/marchingCubes/WMMarchingCubes.h"
#include "../modules/directVolumeRendering/WMDirectVolumeRendering.h"
#include "../modules/navSlices/WMNavSlices.h"
#include "../modules/prototypeBoxManipulation/WMPrototypeBoxManipulation.h"
#include "../modules/voxelizer/WMVoxelizer.h"
#include "../modules/writeNIfTI/WMWriteNIfTI.h"
#include "WModuleFactory.h"
......@@ -87,7 +86,6 @@ void WModuleFactory::load()
m_prototypes.insert( boost::shared_ptr< WModule >( new WMGaussFiltering() ) );
m_prototypes.insert( boost::shared_ptr< WModule >( new WMHud() ) );
m_prototypes.insert( boost::shared_ptr< WModule >( new WMEEGView() ) );
m_prototypes.insert( boost::shared_ptr< WModule >( new WMPrototypeBoxManipulation() ) );
m_prototypes.insert( boost::shared_ptr< WModule >( new WMVoxelizer() ) );
m_prototypes.insert( boost::shared_ptr< WModule >( new WMDirectVolumeRendering() ) );
m_prototypes.insert( boost::shared_ptr< WModule >( new WMWriteNIfTI() ) );
......
......@@ -32,7 +32,11 @@
#include <osg/StateAttribute>
#include "../../kernel/WKernel.h"
#include "../../dataHandler/WDataTexture3D.h"
#include "../../common/WColor.h"
#include "../../graphicsEngine/WGEUtils.h"
#include "../../graphicsEngine/WGEGeodeUtils.h"
#include "../../graphicsEngine/WShader.h"
#include "WMDirectVolumeRendering.h"
......@@ -82,10 +86,17 @@ void WMDirectVolumeRendering::properties()
{
// Initialize the properties
m_propCondition = boost::shared_ptr< WCondition >( new WCondition() );
m_isoSurface = m_properties2->addProperty( "Isosurface Mode", "If enabled, the Volume Renderer will render an isosurface and ignores the"
"transfer function.", true );
m_isoValue = m_properties2->addProperty( "Isovalue", "The Isovalue used whenever the Isosurface Mode is turned on.",
50 );
}
void WMDirectVolumeRendering::moduleMain()
{
m_shader = osg::ref_ptr< WShader > ( new WShader( "DVRRaycast" ) );
// let the main loop awake if the data changes or the properties changed.
m_moduleState.setResetable( true, true );
m_moduleState.add( m_input->getDataChangedCondition() );
......@@ -139,7 +150,31 @@ void WMDirectVolumeRendering::moduleMain()
// get the BBox
std::pair< wmath::WPosition, wmath::WPosition > bb = grid->getBoundingBox();
//m_rootNode
// use the OSG Shapes, create unit cube
osg::ref_ptr< osg::Node > cube = wge::generateSolidBoundingBoxNode( bb.first, bb.second, WColor( 0.0, 0.0, 0.0, 1.0 ) );
m_shader->apply( cube );
// bind the texture to the node
osg::ref_ptr< osg::Texture3D > texture3D = m_dataSet->getTexture()->getTexture();
osg::StateSet* rootState = cube->getOrCreateStateSet();
rootState->setTextureAttributeAndModes( 0, texture3D, osg::StateAttribute::ON );
// for the texture, also bind the appropriate uniforms
rootState->addUniform( new osg::Uniform( "tex0", 0 ) );
// setup all those uniforms
osg::ref_ptr< osg::Uniform > isovalue = new osg::Uniform( "u_isovalue", static_cast< float >( m_isoValue->get() / 100.0 ) );
isovalue->setUpdateCallback( new SafeUniformCallback( this ) );
osg::ref_ptr< osg::Uniform > isosurface = new osg::Uniform( "u_isosurface", m_isoSurface->get() );
isosurface->setUpdateCallback( new SafeUniformCallback( this ) );
rootState->addUniform( isovalue );
rootState->addUniform( isosurface );
// update node
WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->remove( m_rootNode );
m_rootNode = cube;
WKernel::getRunningKernel()->getGraphicsEngine()->getScene()->insert( m_rootNode );
}
}
......@@ -150,9 +185,23 @@ void WMDirectVolumeRendering::moduleMain()
void WMDirectVolumeRendering::SafeUpdateCallback::operator()( osg::Node* node, osg::NodeVisitor* nv )
{
// currently, there is nothing to update
traverse( node, nv );
}
void WMDirectVolumeRendering::SafeUniformCallback::operator()( osg::Uniform* uniform, osg::NodeVisitor* nv )
{
// update some uniforms:
if ( m_module->m_isoValue->changed() && ( uniform->getName() == "u_isovalue" ) )
{
uniform->set( static_cast< float >( m_module->m_isoValue->get( true ) / 100.0 ) );
}
if ( m_module->m_isoSurface->changed() && ( uniform->getName() == "u_isosurface" ) )
{
uniform->set( m_module->m_isoSurface->get( true ) );
}
}
void WMDirectVolumeRendering::activate()
{
// Activate/Deactivate the DVR
......
......@@ -27,7 +27,8 @@
#include <string>
#include <osg/Geode>
#include <osg/Node>
#include <osg/Uniform>
#include "../../kernel/WModule.h"
#include "../../kernel/WModuleInputData.h"
......@@ -92,7 +93,7 @@ protected:
/**
* The root node used for this modules graphics. For OSG nodes, always use osg::ref_ptr to ensure proper resource management.
*/
osg::ref_ptr<osg::Geode> m_rootNode;
osg::ref_ptr< osg::Node > m_rootNode;
/**
* Callback for m_active. Overwrite this in your modules to handle m_active changes separately.
......@@ -111,11 +112,26 @@ private:
*/
boost::shared_ptr< WDataSetSingle > m_dataSet;
/**
* If this property is true, as special shader is used which emulates isosurfaces using the m_isoValue property.
*/
WPropBool m_isoSurface;
/**
* The Isovalue used in the case m_isoSurface is true.
*/
WPropInt m_isoValue;
/**
* A condition used to notify about changes in several properties.
*/
boost::shared_ptr< WCondition > m_propCondition;
/**
* the DVR shader.
*/
osg::ref_ptr< WShader > m_shader;
/**
* Node callback to change the color of the shapes inside the root node. For more details on this class, refer to the documentation in
* moduleMain().
......@@ -151,6 +167,36 @@ private:
*/
bool m_initialUpdate;
};
/**
* Class handling uniform update during render traversal
*/
class SafeUniformCallback: public osg::Uniform::Callback
{
public:
/**
* Constructor.
*
* \param module just set the creating module as pointer for later reference.
*/
explicit SafeUniformCallback( WMDirectVolumeRendering* module ): m_module( module )
{
};
/**
* The callback. Called every render traversal for the uniform.
*
* \param uniform the uniform for which this callback is.
* \param nv the visitor.
*/
virtual void operator() ( osg::Uniform* uniform, osg::NodeVisitor* nv );
/**
* Pointer used to access members of the module to modify the node.
*/
WMDirectVolumeRendering* m_module;
};
};
#endif // WMDIRECTVOLUMERENDERING_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
/////////////////////////////////////////////////////////////////////////////
// Varyings
/////////////////////////////////////////////////////////////////////////////
#include "DVRRaycast.varyings"
/////////////////////////////////////////////////////////////////////////////
// Uniforms
/////////////////////////////////////////////////////////////////////////////
// texture containing the data
uniform sampler3D tex0;
// The isovalue to use.
uniform float u_isovalue;
// Should the shader create some kind of isosurface instead of a volume rendering?
uniform bool u_isosurface;
/////////////////////////////////////////////////////////////////////////////
// Attributes
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// Variables
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// Functions
/////////////////////////////////////////////////////////////////////////////
/**
* Main entry point of the fragment shader.
*/
void main()
{
// please do not laugh, it is a very very very simple "isosurface" shader
gl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );
if ( u_isosurface )
{
vec3 curPoint = v_rayStart;
float value;
int i = 0;
while ( i < 250 )
{
i++;
value = texture3D( tex0, curPoint ).r;
if ( value >= u_isovalue )
{
break;
}
else
{
curPoint += 0.005 * v_ray;
}
}
if ( i >= 250 )
{
discard;
}
gl_FragColor = vec4( vec3( 1.0 - i / 150.0 ), 1.0 );
}
}
//---------------------------------------------------------------------------
//
// 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