31 #include <osg/BoundingSphere>
32 #include <osg/Drawable>
34 #include <osg/Geometry>
37 #include "WMImageSpaceTensorLIC.h"
38 #include "WTuringTextureCreator.h"
39 #include "core/common/WPropertyHelper.h"
40 #include "core/common/math/WMath.h"
41 #include "core/dataHandler/WDataHandler.h"
42 #include "core/dataHandler/WDataTexture3D.h"
43 #include "core/dataHandler/WGridRegular3D.h"
44 #include "core/graphicsEngine/WGEColormapping.h"
45 #include "core/graphicsEngine/WGEGeodeUtils.h"
46 #include "core/graphicsEngine/WGETextureUtils.h"
47 #include "core/graphicsEngine/WGEUtils.h"
48 #include "core/graphicsEngine/callbacks/WGELinearTranslationCallback.h"
49 #include "core/graphicsEngine/callbacks/WGENodeMaskCallback.h"
50 #include "core/graphicsEngine/callbacks/WGEShaderAnimationCallback.h"
51 #include "core/graphicsEngine/offscreen/WGEOffscreenRenderNode.h"
52 #include "core/graphicsEngine/offscreen/WGEOffscreenRenderPass.h"
53 #include "core/graphicsEngine/shaders/WGEPropertyUniform.h"
54 #include "core/graphicsEngine/shaders/WGEShader.h"
55 #include "core/graphicsEngine/shaders/WGEShaderDefineOptions.h"
56 #include "core/graphicsEngine/shaders/WGEShaderPropertyDefineOptions.h"
57 #include "core/kernel/WKernel.h"
72 void genReactionDiffusion(
unsigned char* target,
73 unsigned int tileWidth,
unsigned int tileHeight,
74 unsigned int width,
unsigned int ,
75 unsigned int iterations,
77 float spotIrregularity )
86 float grid1Base = 4.0;
87 std::vector< std::vector< float > > grid1( tileWidth,
88 std::vector< float >( tileHeight, grid1Base ) );
90 float grid2Base = 4.0;
91 std::vector< std::vector< float > > grid2( tileWidth,
92 std::vector< float >( tileHeight, grid2Base ) );
94 std::vector< std::vector< float > > delta1( tileWidth,
95 std::vector< float >( tileHeight, 0.0f ) );
96 std::vector< std::vector< float > > delta2( tileWidth,
97 std::vector< float >( tileHeight, 0.0f ) );
99 std::vector< std::vector< float > > noise( tileWidth,
100 std::vector< float >( tileHeight, 0.0f ) );
102 float noiseRangeMin = 0.1;
103 float noiseRangeMax = 5.0;
106 noiseRangeMin + ( ( noiseRangeMax - noiseRangeMin ) *
108 float noiseBase = 12.0;
115 srand48( time( 0 ) );
116 for(
unsigned int y = 0; y < tileHeight; y++ )
118 for(
unsigned int x = 0; x < tileWidth; x++ )
122 noise[ x ][ y ] = noiseBase + ( -noiseRange + ( drand48() * 2.0 * noiseRange ) );
134 float ka = ( kaMin + ( ( kaMax - kaMin ) * ( 1.0 - spotSize ) ) ) / 15.0;
135 float d1= 0.25 / 2.0;
136 float d2= 0.0625 / 2.0;
139 for(
unsigned int iteration = 0; iteration < iterations; iteration++ )
142 for(
unsigned int i = 0; i < tileWidth; i++ )
145 unsigned int iPrev = ( i + tileWidth - 1 ) % tileWidth;
146 unsigned int iNext = ( i + 1 ) % tileWidth;
148 for(
unsigned int j = 0; j < tileHeight; j++ )
151 unsigned int jPrev = ( j + tileHeight - 1 ) % tileHeight;
152 unsigned int jNext = ( j + 1 ) % tileHeight;
168 float laplacian1 = grid1[ i ][ jPrev ] + grid1[ i ][ jNext ] + grid1[ iPrev ][ j ] +
169 grid1[ iNext ][ j ] - 4.0 * grid1[ i ][ j ];
170 float laplacian2 = grid2[ i ][ jPrev ] + grid2[ i ][ jNext ] + grid2[ iPrev ][ j ] +
171 grid2[ iNext ][ j ] - 4.0 * grid2[ i ][ j ];
175 ka * ( 16 - grid1[ i ][ j ] * grid2[ i ][ j ] ) + d1 * laplacian1;
177 ka * ( grid1[ i ][ j ] * grid2[ i ][ j ] - grid2[ i ][ j ] - noise[ i ][ j ] ) +
186 for(
unsigned int i = 0; i < tileWidth; i++ )
188 for(
unsigned int j = 0; j < tileHeight; j++ )
190 grid1[ i ][ j ] += ( speed * delta1[ i ][ j ] );
191 grid2[ i ][ j ] += ( speed * delta2[ i ][ j ] );
192 if( grid2[ i ][ j ] < 0 )
195 if( grid1[ i ][ j ] < grid1Min )
196 grid1Min = grid1[ i ][ j ];
197 if( grid1[ i ][ j ] > grid1Max )
198 grid1Max = grid1[ i ][ j ];
207 for(
unsigned int x = 0; x < tileWidth; x++ )
209 for(
unsigned int y = 0; y < tileHeight; y++ )
211 target[ ( y * width ) + x ] =
212 255.0 * ( grid1[ x ][ y ] - grid1Min ) / ( grid1Max - grid1Min );
234 return "Image Space Tensor LIC";
286 m_useLight =
m_licGroup->addProperty(
"Use Light",
"Check to enable lightning using the Phong model.",
false );
293 m_useEdgesStep =
m_licGroup->addProperty(
"Edge Step",
"Define the steepness of the blend function between color and edge color.", 1.0 );
297 m_cmapRatio =
m_licGroup->addProperty(
"Ratio Colormap to LIC",
"Blending ratio between LIC and colormap.", 0.5 );
305 "modification of this size.", 1.5 );
309 m_numIters =
m_advancedLicGroup->addProperty(
"Number of Iterations",
"How much iterations along a streamline should be done per frame.",
315 "tangential plane of the surface and the vector which is going to be projected. You can adjust how steep a vector can be before it is "
316 "clipped and NOT projected. Note: all vectors with an angle below this threshold are projected but linearly reduced in influence "
317 "depending on the angle.", 90.0 );
338 osg::Geometry* surfaceGeometry =
new osg::Geometry();
339 osg::ref_ptr< osg::Geode > surfaceGeode = osg::ref_ptr< osg::Geode >(
new osg::Geode );
341 surfaceGeometry->setVertexArray( mesh->getVertexArray() );
342 osg::DrawElementsUInt* surfaceElement;
343 surfaceElement =
new osg::DrawElementsUInt( osg::PrimitiveSet::TRIANGLES, 0 );
344 std::vector< size_t > tris = mesh->getTriangles();
345 surfaceElement->reserve( tris.size() );
346 for(
unsigned int vertId = 0; vertId < tris.size(); ++vertId )
348 surfaceElement->push_back( tris[vertId] );
350 surfaceGeometry->addPrimitiveSet( surfaceElement );
353 surfaceGeometry->setNormalArray( mesh->getVertexNormalArray() );
354 surfaceGeometry->setNormalBinding( osg::Geometry::BIND_PER_VERTEX );
357 surfaceGeometry->setTexCoordArray( 0, mesh->getTextureCoordinateArray() );
360 surfaceGeode->addDrawable( surfaceGeometry );
365 warnLog() <<
"No surface connected to input but surface render mode enabled. Nothing rendered.";
370 osg::ref_ptr< osg::Node > xSlice =
wge::genFinitePlane( grid->getOrigin(), grid->getNbCoordsY() * grid->getDirectionY(),
371 grid->getNbCoordsZ() * grid->getDirectionZ() );
373 osg::ref_ptr< osg::Node > ySlice =
wge::genFinitePlane( grid->getOrigin(), grid->getNbCoordsX() * grid->getDirectionX(),
374 grid->getNbCoordsZ() * grid->getDirectionZ() );
376 osg::ref_ptr< osg::Node > zSlice =
wge::genFinitePlane( grid->getOrigin(), grid->getNbCoordsX() * grid->getDirectionX(),
377 grid->getNbCoordsY() * grid->getDirectionY() );
380 xSlice->setName(
"_X SLice" );
381 ySlice->setName(
"_Y SLice" );
382 zSlice->setName(
"_Z SLice" );
386 osg::StateSet* ss = xSlice->getOrCreateStateSet();
388 ss->addUniform(
new osg::Uniform(
"u_vertexShiftDirection", grid->getDirectionX().as< osg::Vec3f >() ) );
389 ss = ySlice->getOrCreateStateSet();
391 ss->addUniform(
new osg::Uniform(
"u_vertexShiftDirection", grid->getDirectionY().as< osg::Vec3f >() ) );
392 ss = zSlice->getOrCreateStateSet();
394 ss->addUniform(
new osg::Uniform(
"u_vertexShiftDirection", grid->getDirectionZ().as< osg::Vec3f >() ) );
402 xSlice->setCullingActive(
false );
403 ySlice->setCullingActive(
false );
404 zSlice->setCullingActive(
false );
430 const size_t resX = 128;
432 float rdSpot = 0.689;
433 unsigned int rdIter = 4000;
436 osg::ref_ptr< osg::Image > ima =
new osg::Image;
437 ima->allocateImage( resX, resX, 1, GL_LUMINANCE, GL_UNSIGNED_BYTE );
438 genReactionDiffusion( ima->data(), resX, resX, resX, resX, rdIter, rdSpot, rdIrr );
441 randTexture->setWrap( osg::Texture::WRAP_S, osg::Texture::REPEAT );
442 randTexture->setWrap( osg::Texture::WRAP_T, osg::Texture::REPEAT );
466 osg::ref_ptr< WGEShader > transformationShader =
new WGEShader(
"WMImageSpaceTensorLIC-Transformation",
m_localPath );
473 osg::ref_ptr< WGEOffscreenRenderPass > transformation = offscreen->addGeometryRenderPass(
475 transformationShader,
478 transformation->bind( randTexture, 3 );
482 osg::ref_ptr< WGEShader > edgeShader =
new WGEShader(
"WMImageSpaceTensorLIC-Edge",
m_localPath );
483 osg::ref_ptr< WGEOffscreenRenderPass > edgeDetection = offscreen->addTextureProcessingPass(
490 osg::ref_ptr< WGEOffscreenRenderPass > advection = offscreen->addTextureProcessingPass(
496 osg::ref_ptr< WGEOffscreenRenderPass > clipBlend = offscreen->addTextureProcessingPass(
502 osg::ref_ptr< WGEOffscreenRenderPass > postprocessing = offscreen->addFinalOnScreenPass(
513 osg::ref_ptr< osg::Texture2D > transformationOut1 = transformation->attach( WGECamera::COLOR_BUFFER0 );
514 osg::ref_ptr< osg::Texture2D > transformationOut2 = transformation->attach( WGECamera::COLOR_BUFFER1 );
515 osg::ref_ptr< osg::Texture2D > transformationOut3 = transformation->attach( WGECamera::COLOR_BUFFER2 );
516 osg::ref_ptr< osg::Texture2D > transformationColormapped = transformation->attach( WGECamera::COLOR_BUFFER3 );
517 osg::ref_ptr< osg::Texture2D > transformationDepth = transformation->attach( WGECamera::DEPTH_BUFFER );
525 osg::ref_ptr< osg::Texture2D > edgeDetectionOut1 = edgeDetection->attach( WGECamera::COLOR_BUFFER0 );
526 edgeDetection->bind( transformationDepth, 0 );
527 edgeDetection->bind( transformationOut2, 1 );
531 osg::ref_ptr< osg::Texture2D > advectionOutA = advection->attach( WGECamera::COLOR_BUFFER0, GL_RGBA );
532 advection->bind( transformationOut1, 0 );
533 advection->bind( edgeDetectionOut1, 1 );
537 advection->addUniform( numIters );
539 osg::Uniform* animationTime(
new osg::Uniform(
"u_animation", 0 ) );
541 advection->addUniform( animationTime );
544 advectionOutA->setFilter( osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR );
545 edgeDetectionOut1->setFilter( osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR );
546 transformationColormapped->setFilter( osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR );
549 osg::ref_ptr< osg::Texture2D > merged = clipBlend->attach( WGECamera::COLOR_BUFFER0, GL_RGBA );
550 clipBlend->bind( advectionOutA, 0 );
551 clipBlend->bind( edgeDetectionOut1, 1 );
552 clipBlend->bind( transformationColormapped, 2 );
553 clipBlend->bind( transformationOut2, 3 );
554 clipBlend->bind( transformationOut3, 4 );
565 postprocessing->getOrCreateStateSet()->setMode( GL_BLEND, osg::StateAttribute::ON );
568 postprocessing->bind( advectionOutA, 0 );
569 postprocessing->bind( edgeDetectionOut1, 1 );
570 postprocessing->bind( transformationColormapped, 2 );
571 postprocessing->bind( transformationOut2, 3 );
572 postprocessing->bind( transformationOut3, 4 );
573 postprocessing->bind( merged, 5 );
584 m_root->insert( offscreen );
587 osg::ref_ptr< osg::Node > cullProxy;
611 std::shared_ptr< WDataSetVector > dataSetEvec1 =
m_evec1In->getData();
612 std::shared_ptr< WDataSetVector > dataSetEvec2 =
m_evec2In->getData();
613 std::shared_ptr< WDataSetVector > dataSetEvals =
m_evalsIn->getData();
614 std::shared_ptr< WTriangleMesh > mesh =
m_meshIn->getData();
616 bool dataValid = ( dataSetEvals && dataSetEvec1 && dataSetEvec2 );
627 if( dataValid && !dataUpdated && !propertyUpdated )
633 std::shared_ptr< WGridRegular3D > grid;
635 grid = std::dynamic_pointer_cast< WGridRegular3D >( dataSetEvec1->getGrid() );
636 m_xPos->setMax( grid->getNbCoordsX() - 1 );
637 m_yPos->setMax( grid->getNbCoordsY() - 1 );
638 m_zPos->setMax( grid->getNbCoordsZ() - 1 );
642 transformation->bind( dataSetEvec1->getTexture(), 0 );
643 transformation->bind( dataSetEvec2->getTexture(), 1 );
644 transformation->bind( dataSetEvals->getTexture(), 2 );
649 m_root->remove( cullProxy );
651 m_root->insert( cullProxy );
virtual void wait() const
Wait for the condition.
void setResetable(bool resetable=true, bool autoReset=true)
Sets the resetable flag.
virtual void add(std::shared_ptr< WCondition > condition)
Adds another condition to the set of conditions to wait for.
Class to encapsulate boost::condition_variable_any.
static void apply(osg::ref_ptr< osg::Node > node, WMatrix4d preTransform=WMatrix4d::identity(), osg::ref_ptr< WGEShader > shader=osg::ref_ptr< WGEShader >(), size_t startTexUnit=0)
Apply the colormapping to the specified node.
Class to wrap around the osg Group node and providing a thread safe add/removal mechanism.
This class adds some convenience methods to WGEGroupNode.
This callback is useful to en-/disable nodes using the node mask based on properties.
This type of node basically is a convenience class for managing and creating offscreen renderings.
This is a uniform callback setting the uniform to the current time in milliseconds,...
std::shared_ptr< WGEShaderPreprocessor > SPtr
Shared pointer for this class.
This is a WGEShaderDefineOptions class which additionally uses a property to automatically control th...
Class encapsulating the OSG Program class for a more convenient way of adding and modifying shader.
This calls serves a simple purpose: have a texture and its scaling information together which allows ...
osg::ref_ptr< WGETexture< TextureType > > SPtr
Convenience type for OSG reference pointer on WGETextures.
static WKernel * getRunningKernel()
Returns pointer to the currently running kernel.
std::shared_ptr< WGraphicsEngine > getGraphicsEngine() const
Returns pointer to currently running instance of graphics engine.
WPropBool m_useLight
indicates whether to use Phong
virtual void connectors()
Initialize the connectors this module is using.
std::shared_ptr< WCondition > m_propCondition
A condition used to notify about changes in several properties.
WPropDouble m_lightIntensity
light intensity
WPropDouble m_cmapRatio
the ratio between colormap and LIC
WPropGroup m_geometryGroup
the group contains several input geometry parameters
WMImageSpaceTensorLIC()
Default constructor.
WPropDouble m_faClip
Clipp according to FA.
WPropInt m_yPos
y position of the slice
virtual std::shared_ptr< WModule > factory() const
Due to the prototype design pattern used to build modules, this method returns a new instance of this...
WPropBool m_showonX
indicates whether the vector should be shown on slice X
virtual void moduleMain()
Entry point after loading the module.
WPropInt m_xPos
x position of the slice
std::shared_ptr< WModuleInputData< WDataSetVector > > m_evec2In
The input connector containing the DTI field whose derived field is used for LIC.
WPropBool m_showonZ
indicates whether the vector should be shown on slice Z
void initOSG(std::shared_ptr< WGridRegular3D > grid, std::shared_ptr< WTriangleMesh > mesh)
Initializes the needed geodes, transformations and vertex arrays.
WPropDouble m_useEdgesStep
define the steepness of the step function used to blend in the edge color.
WPropGroup m_advancedLicGroup
The group for more advanced LIC features.
virtual ~WMImageSpaceTensorLIC()
Destructor.
WPropDouble m_noiseRes
The resolution scaling for the noise.
std::shared_ptr< WModuleInputData< WDataSetVector > > m_evalsIn
The input connector containing the DTI field whose derived field is used for LIC.
virtual const std::string getDescription() const
Gives back a description of this module.
osg::ref_ptr< WGEGroupNode > m_output
The Geode containing all the slices and the mesh.
osg::ref_ptr< WGEManagedGroupNode > m_root
Scene root node.
std::shared_ptr< WModuleInputData< WDataSetVector > > m_evec1In
The input connector containing the DTI field whose derived field is used for LIC.
WPropInt m_numIters
the number of iterations done per frame
WPropBool m_useSlices
indicates whether the vector should be shown on slices or input geometry
WPropBool m_showonY
indicates whether the vector should be shown on slice Y
WPropBool m_useEdges
indicates whether to show the edges
WPropColor m_useEdgesColor
indicated whether the edges (if enabled) should be black or white or green or red or ....
virtual const std::string getName() const
Gives back the name of this module.
std::shared_ptr< WModuleInputData< WTriangleMesh > > m_meshIn
The input containing the surface on which the LIC should be applied on.
WPropGroup m_sliceGroup
the group contains several slice properties
WPropDouble m_projectionAngleThreshold
the angle threshold between surface and vector before clipping the vector.
WPropBool m_showHUD
indicates whether to show the texture HUD
WPropInt m_zPos
z position of the slice
WPropGroup m_licGroup
the group contains several LIC properties
virtual void properties()
Initialize the properties for this module.
Class representing a single module of OpenWalnut.
boost::filesystem::path m_localPath
The path where the module binary resides in.
virtual void properties()
Initialize properties in this function.
wlog::WStreamedLogger debugLog() const
Logger instance for comfortable debug logging.
wlog::WStreamedLogger warnLog() const
Logger instance for comfortable warning- logs.
std::shared_ptr< WProperties > m_properties
The property object for the module.
void ready()
Call this whenever your module is ready and can react on property changes.
WConditionSet m_moduleState
The internal state of the module.
WPropBool m_active
True whenever the module should be active.
virtual void connectors()
Initialize connectors in this function.
WBoolFlag m_shutdownFlag
Condition getting fired whenever the thread should quit.
osg::ref_ptr< osg::Node > generateCullProxy(const WBoundingBox &bbox)
Generate a proxy cube, which ensures OSG does proper near-far plane calculation and culling.
osg::ref_ptr< osg::Geode > genFinitePlane(double xSize, double ySize, const WPlane &p, const WColor &color=WColor(0.0, 0.7, 0.7, 1.0), bool border=false)
Generates a geode out of a Plane with a fixed size in direction of the vectors which span that plane.