Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
campvis-public
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
9
Issues
9
List
Boards
Labels
Service Desk
Milestones
Iterations
Merge Requests
1
Merge Requests
1
Requirements
Requirements
List
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Operations
Operations
Incidents
Analytics
Analytics
Code Review
Insights
Issue
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
CAMP
campvis-public
Commits
2b581529
Commit
2b581529
authored
Oct 07, 2014
by
Christian Schulte zu Berge
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'particle-visualization' into 'development'
Particle visualization See merge request !95
parents
fedbc913
f5cda4fc
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
821 additions
and
3 deletions
+821
-3
ext/tgt/shadermanager.cpp
ext/tgt/shadermanager.cpp
+10
-0
ext/tgt/shadermanager.h
ext/tgt/shadermanager.h
+4
-0
ext/tgt/vertexarrayobject.cpp
ext/tgt/vertexarrayobject.cpp
+4
-0
ext/tgt/vertexarrayobject.h
ext/tgt/vertexarrayobject.h
+6
-0
modules/vectorfield/glsl/particleflowrenderer.frag
modules/vectorfield/glsl/particleflowrenderer.frag
+68
-0
modules/vectorfield/glsl/particleflowrenderer.vert
modules/vectorfield/glsl/particleflowrenderer.vert
+117
-0
modules/vectorfield/pipelines/vectorfielddemo.cpp
modules/vectorfield/pipelines/vectorfielddemo.cpp
+46
-3
modules/vectorfield/pipelines/vectorfielddemo.h
modules/vectorfield/pipelines/vectorfielddemo.h
+8
-0
modules/vectorfield/processors/particleflowrenderer.cpp
modules/vectorfield/processors/particleflowrenderer.cpp
+408
-0
modules/vectorfield/processors/particleflowrenderer.h
modules/vectorfield/processors/particleflowrenderer.h
+150
-0
No files found.
ext/tgt/shadermanager.cpp
View file @
2b581529
...
...
@@ -1322,6 +1322,16 @@ void Shader::setNormalizedAttribute(GLint index, const Vector4<GLuint>& v) {
glVertexAttrib4Nuiv
(
index
,
v
.
elem
);
}
bool
Shader
::
selectSubroutine
(
ShaderObject
::
ShaderType
type
,
const
std
::
string
&
subroutineName
)
{
GLuint
index
=
glGetSubroutineIndex
(
id_
,
type
,
subroutineName
.
c_str
());
if
(
index
==
GL_INVALID_INDEX
)
{
LWARNING
(
"Failed to locate subroutine Location: "
<<
subroutineName
);
return
false
;
}
glUniformSubroutinesuiv
(
type
,
1
,
&
index
);
return
true
;
}
//------------------------------------------------------------------------------
const
string
ShaderManager
::
loggerCat_
(
"tgt.Shader.Manager"
);
...
...
ext/tgt/shadermanager.h
View file @
2b581529
...
...
@@ -258,6 +258,10 @@ public:
std
::
string
getLinkerLog
()
const
;
// Subroutines
bool
selectSubroutine
(
ShaderObject
::
ShaderType
type
,
const
std
::
string
&
subroutineName
);
//
// Uniform stuff
//
...
...
ext/tgt/vertexarrayobject.cpp
View file @
2b581529
...
...
@@ -80,4 +80,8 @@ namespace tgt {
tgtAssert
(
false
,
"Could not find Vertex Attribute location for this BufferObject. You have to add it first using setVertexAttributePointer()!"
);
}
GLuint
VertexArrayObject
::
getId
()
const
{
return
_id
;
}
}
\ No newline at end of file
ext/tgt/vertexarrayobject.h
View file @
2b581529
...
...
@@ -30,6 +30,12 @@ namespace tgt {
*/
~
VertexArrayObject
();
/**
* Returns the OpneGL object ID
* \return _id
*/
GLuint
getId
()
const
;
/**
* Binds this VertexArrayObject to the current OpenGL context.
*/
...
...
modules/vectorfield/glsl/particleflowrenderer.frag
0 → 100644
View file @
2b581529
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012-2014, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// Chair for Computer Aided Medical Procedures
// Technische Universitaet Muenchen
// Boltzmannstr. 3, 85748 Garching b. Muenchen, Germany
//
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
// except in compliance with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions
// and limitations under the License.
//
// ================================================================================================
#include "tools/shading.frag"
#include "tools/transferfunction.frag"
in
vec3
ex_Velocity
;
in
float
ex_Transparency
;
out
vec4
out_Color
;
///< outgoing fragment color
uniform
sampler1D
_transferFunction
;
uniform
TFParameters1D
_transferFunctionParams
;
uniform
int
_coloringMode
;
uniform
float
_scale
;
uniform
vec2
_threshold
;
void
main
()
{
if
(
length
(
gl_PointCoord
-
vec2
(
0
.
5
))
>
0
.
5
)
{
discard
;
}
switch
(
_coloringMode
)
{
case
0
:
// age
out_Color
=
lookupTF
(
_transferFunction
,
_transferFunctionParams
,
ex_Transparency
);
break
;
case
1
:
// velocity
float
f
=
length
(
ex_Velocity
);
f
-=
_threshold
.
x
;
f
/=
(
_threshold
.
y
-
_threshold
.
x
);
f
*=
_scale
;
out_Color
=
lookupTF
(
_transferFunction
,
_transferFunctionParams
,
f
);
break
;
case
2
:
// direction
out_Color
=
vec4
(
normalize
(
abs
(
ex_Velocity
)),
1
.
0
);
break
;
default:
discard
;
}
#ifdef ENABLE_SHADING___
// compute gradient (needed for shading and normals)
vec3
gradient
=
ex_Normal
;
out_Color
.
rgb
=
calculatePhongShading
(
ex_Position
,
_lightSource
,
_cameraPosition
,
gradient
,
_color
.
rgb
,
_color
.
rgb
,
vec3
(
1
.
0
,
1
.
0
,
1
.
0
));
#endif
}
modules/vectorfield/glsl/particleflowrenderer.vert
0 → 100644
View file @
2b581529
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012-2014, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// Chair for Computer Aided Medical Procedures
// Technische Universitaet Muenchen
// Boltzmannstr. 3, 85748 Garching b. Muenchen, Germany
//
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
// except in compliance with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions
// and limitations under the License.
//
// ================================================================================================
#include "tools/texture3d.frag"
subroutine
void
RenderPassType
();
subroutine
uniform
RenderPassType
RenderPass
;
layout
(
location
=
0
)
in
vec3
in_Position
;
layout
(
location
=
1
)
in
vec3
in_Velocity
;
layout
(
location
=
2
)
in
float
in_StartTime
;
layout
(
location
=
3
)
in
vec3
in_InitialPosition
;
out
vec3
ex_Position
;
out
vec3
ex_Velocity
;
out
float
ex_StartTime
;
out
float
ex_Transparency
;
/// Matrix defining model-to-world transformation
uniform
mat4
_modelMatrix
=
mat4
(
1
.
0
,
0
.
0
,
0
.
0
,
0
.
0
,
0
.
0
,
1
.
0
,
0
.
0
,
0
.
0
,
0
.
0
,
0
.
0
,
1
.
0
,
0
.
0
,
0
.
0
,
0
.
0
,
0
.
0
,
1
.
0
);
/// Matrix defining view transformation
uniform
mat4
_viewMatrix
=
mat4
(
1
.
0
,
0
.
0
,
0
.
0
,
0
.
0
,
0
.
0
,
1
.
0
,
0
.
0
,
0
.
0
,
0
.
0
,
0
.
0
,
1
.
0
,
0
.
0
,
0
.
0
,
0
.
0
,
0
.
0
,
1
.
0
);
/// Matrix defining projection transformation
uniform
mat4
_projectionMatrix
=
mat4
(
1
.
0
,
0
.
0
,
0
.
0
,
0
.
0
,
0
.
0
,
1
.
0
,
0
.
0
,
0
.
0
,
0
.
0
,
0
.
0
,
1
.
0
,
0
.
0
,
0
.
0
,
0
.
0
,
0
.
0
,
1
.
0
);
uniform
float
_time
;
uniform
float
_frameLength
;
uniform
float
_lifetime
;
uniform
float
_scale
;
uniform
vec2
_threshold
;
uniform
sampler3D
_volume
;
uniform
TextureParameters3D
_volumeTextureParams
;
subroutine
(
RenderPassType
)
void
update
()
{
if
(
_time
>
in_StartTime
)
{
float
age
=
_time
-
in_StartTime
;
if
(
age
>
_lifetime
||
length
(
in_Velocity
)
<
_threshold
.
x
||
length
(
in_Velocity
)
>
_threshold
.
y
)
{
// particle expired, recycle
ex_Position
=
in_InitialPosition
;
ex_Velocity
=
texture
(
_volume
,
(
ex_Position
/
_volumeTextureParams
.
_size
).
xyz
).
xyz
;
ex_StartTime
=
_time
;
}
else
{
// particle alive, advance
ex_Position
=
in_Position
+
(
in_Velocity
*
_frameLength
*
0
.
05
*
_scale
);
// compute new velocity by mixture of old velocity and flow at current location, model some inertia
vec3
v
=
texture
(
_volume
,
(
ex_Position
/
_volumeTextureParams
.
_size
).
xyz
).
xyz
;
ex_Velocity
=
mix
(
in_Velocity
,
v
,
0
.
5
);
//smoothstep(0.5, 2.0, v/in_Velocity));
ex_StartTime
=
in_StartTime
;
}
}
else
{
ex_Position
=
in_Position
;
ex_Velocity
=
in_Velocity
;
ex_StartTime
=
in_StartTime
;
}
}
subroutine
(
RenderPassType
)
void
render
()
{
float
age
=
_time
-
in_StartTime
;
ex_Transparency
=
(
age
>=
0
.
0
)
?
1
.
0
-
(
age
/
_lifetime
)
:
0
.
0
;
gl_Position
=
_projectionMatrix
*
(
_viewMatrix
*
(
_modelMatrix
*
vec4
(
in_Position
,
1
.
0
)));
//ex_Position = in_Position;
mat4
normalMatrix
=
transpose
(
inverse
(
_modelMatrix
));
//vec4 normalTmp = (normalMatrix * vec4(in_Normal, 0.0));
// ex_Normal = normalize((normalTmp).xyz);
}
void
main
()
{
// call the current subroutine
RenderPass
();
}
modules/vectorfield/pipelines/vectorfielddemo.cpp
View file @
2b581529
...
...
@@ -28,24 +28,35 @@
#include "core/classification/geometry1dtransferfunction.h"
#include "core/classification/tfgeometry1d.h"
#include "core/datastructures/imagedata.h"
namespace
campvis
{
static
const
GenericOption
<
std
::
string
>
viewSelectionOptions
[
2
]
=
{
GenericOption
<
std
::
string
>
(
"arrows"
,
"Arrows"
),
GenericOption
<
std
::
string
>
(
"particles"
,
"Particle Simulation"
),
};
VectorFieldDemo
::
VectorFieldDemo
(
DataContainer
*
dc
)
:
AutoEvaluationPipeline
(
dc
)
,
_lsp
()
,
_imageReader
()
,
_vectorFieldReader
()
,
_pfr
(
&
_canvasSize
)
,
_vectorFieldRenderer
(
&
_canvasSize
)
,
_sliceRenderer
(
&
_canvasSize
)
,
_rtc
(
&
_canvasSize
)
,
p_camera
(
"Camera"
,
"Camera"
,
tgt
::
Camera
())
,
p_sliceNumber
(
"SliceNuber"
,
"Slice Number"
,
0
,
0
,
1024
)
,
p_viewSelection
(
"ViewSelection"
,
"Select 3D View"
,
viewSelectionOptions
,
2
)
,
p_time
(
"Time"
,
"Time"
,
0
,
0
,
100
)
,
_trackballEH
(
0
)
{
addProperty
(
p_camera
);
addProperty
(
p_sliceNumber
);
addProperty
(
p_viewSelection
);
addProperty
(
p_time
);
_trackballEH
=
new
TrackballNavigationEventListener
(
&
p_camera
,
&
_canvasSize
);
addEventListenerToBack
(
_trackballEH
);
...
...
@@ -53,6 +64,7 @@ namespace campvis {
addProcessor
(
&
_lsp
);
addProcessor
(
&
_imageReader
);
addProcessor
(
&
_vectorFieldReader
);
addProcessor
(
&
_pfr
);
addProcessor
(
&
_vectorFieldRenderer
);
addProcessor
(
&
_sliceRenderer
);
addProcessor
(
&
_rtc
);
...
...
@@ -65,6 +77,7 @@ namespace campvis {
AutoEvaluationPipeline
::
init
();
p_camera
.
addSharedProperty
(
&
_vectorFieldRenderer
.
p_camera
);
p_camera
.
addSharedProperty
(
&
_pfr
.
p_camera
);
p_camera
.
addSharedProperty
(
&
_sliceRenderer
.
p_camera
);
p_sliceNumber
.
addSharedProperty
(
&
_vectorFieldRenderer
.
p_sliceNumber
);
...
...
@@ -78,9 +91,10 @@ namespace campvis {
_vectorFieldReader
.
p_url
.
setValue
(
CAMPVIS_SOURCE_DIR
"/modules/vectorfield/sampledata/result_vec.mhd"
);
_vectorFieldReader
.
p_targetImageID
.
setValue
(
"vectors"
);
_vectorFieldReader
.
p_targetImageID
.
addSharedProperty
(
&
_pfr
.
p_inputVectors
);
_vectorFieldReader
.
p_targetImageID
.
addSharedProperty
(
&
_vectorFieldRenderer
.
p_inputVectors
);
_vectorFieldRenderer
.
p_renderOutput
.
addSharedProperty
(
&
_rtc
.
p_firstImageId
);
_vectorFieldRenderer
.
p_renderOutput
.
setValue
(
"arrows"
);
_vectorFieldRenderer
.
p_arrowSize
.
setValue
(
0.03
f
);
_vectorFieldRenderer
.
p_lenThresholdMin
.
setValue
(
100.
f
);
_vectorFieldRenderer
.
p_flowProfile1
.
setValue
(
0.4716088614374652
f
);
...
...
@@ -90,24 +104,53 @@ namespace campvis {
_vectorFieldRenderer
.
p_lenThresholdMax
.
setValue
(
400.
f
);
_vectorFieldRenderer
.
p_sliceOrientation
.
setValue
(
3
);
_pfr
.
p_lenThresholdMin
.
setValue
(
100.
f
);
_pfr
.
p_flowProfile1
.
setValue
(
0.4716088614374652
f
);
_pfr
.
p_flowProfile2
.
setValue
(
0.0638348311845516
f
);
_pfr
.
p_flowProfile3
.
setValue
(
0.1713471562960614
f
);
_pfr
.
p_flowProfile4
.
setValue
(
0.1019371804834016
f
);
_pfr
.
p_lenThresholdMax
.
setValue
(
400.
f
);
_pfr
.
p_renderOutput
.
setValue
(
"particles"
);
_pfr
.
setEnabled
(
false
);
Geometry1DTransferFunction
*
tf
=
new
Geometry1DTransferFunction
(
128
,
tgt
::
vec2
(
0.
f
,
1.
f
));
tf
->
addGeometry
(
TFGeometry1D
::
createQuad
(
tgt
::
vec2
(
0.
f
,
1.
f
),
tgt
::
col4
(
0
,
0
,
0
,
255
),
tgt
::
col4
(
255
,
255
,
255
,
255
)));
_sliceRenderer
.
p_transferFunction
.
replaceTF
(
tf
);
_sliceRenderer
.
p_targetImageID
.
setValue
(
"slice"
);
_sliceRenderer
.
p_targetImageID
.
addSharedProperty
(
&
_rtc
.
p_secondImageId
);
_rtc
.
p_firstImageId
.
setValue
(
"arrows"
);
_rtc
.
p_secondImageId
.
setValue
(
"slice"
);
_rtc
.
p_compositingMethod
.
selectById
(
"depth"
);
_rtc
.
p_targetImageId
.
setValue
(
"composed"
);
_renderTargetID
.
setValue
(
"composed"
);
p_time
.
addSharedProperty
(
&
_vectorFieldRenderer
.
p_Time
);
p_time
.
addSharedProperty
(
&
_pfr
.
p_Time
);
}
void
VectorFieldDemo
::
onProcessorValidated
(
AbstractProcessor
*
processor
)
{
if
(
processor
==
&
_imageReader
)
{
// update camera
ScopedTypedData
<
I
HasWorldBounds
>
img
(
*
_data
,
_sliceRenderer
.
p_sourceImageID
.
getValue
());
ScopedTypedData
<
I
mageData
>
img
(
*
_data
,
_sliceRenderer
.
p_sourceImageID
.
getValue
());
if
(
img
)
{
_trackballEH
->
reinitializeCamera
(
img
);
p_sliceNumber
.
setMaxValue
(
static_cast
<
int
>
(
img
->
getSize
().
z
));
}
}
}
void
VectorFieldDemo
::
onPropertyChanged
(
const
AbstractProperty
*
prop
)
{
if
(
prop
==
&
p_viewSelection
)
{
if
(
p_viewSelection
.
getOptionValue
()
==
"arrows"
)
{
_rtc
.
p_firstImageId
.
setValue
(
"arrows"
);
_vectorFieldRenderer
.
setEnabled
(
true
);
_pfr
.
setEnabled
(
false
);
}
else
if
(
p_viewSelection
.
getOptionValue
()
==
"particles"
)
{
_rtc
.
p_firstImageId
.
setValue
(
"particles"
);
_vectorFieldRenderer
.
setEnabled
(
false
);
_pfr
.
setEnabled
(
true
);
}
}
}
...
...
modules/vectorfield/pipelines/vectorfielddemo.h
View file @
2b581529
...
...
@@ -32,6 +32,7 @@
#include "modules/base/processors/lightsourceprovider.h"
#include "modules/io/processors/mhdimagereader.h"
#include "modules/vectorfield/processors/particleflowrenderer.h"
#include "modules/vectorfield/processors/vectorfieldrenderer.h"
#include "modules/vis/processors/slicerenderer3d.h"
#include "modules/vis/processors/rendertargetcompositor.h"
...
...
@@ -65,15 +66,22 @@ namespace campvis {
*/
virtual
void
onProcessorValidated
(
AbstractProcessor
*
processor
);
/// \see HasPropertyCollection::onPropertyChanged
virtual
void
onPropertyChanged
(
const
AbstractProperty
*
prop
);
LightSourceProvider
_lsp
;
MhdImageReader
_imageReader
;
MhdImageReader
_vectorFieldReader
;
ParticleFlowRenderer
_pfr
;
VectorFieldRenderer
_vectorFieldRenderer
;
SliceRenderer3D
_sliceRenderer
;
RenderTargetCompositor
_rtc
;
CameraProperty
p_camera
;
IntProperty
p_sliceNumber
;
GenericOptionProperty
<
std
::
string
>
p_viewSelection
;
IntProperty
p_time
;
TrackballNavigationEventListener
*
_trackballEH
;
};
...
...
modules/vectorfield/processors/particleflowrenderer.cpp
0 → 100644
View file @
2b581529
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012-2014, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// Chair for Computer Aided Medical Procedures
// Technische Universitaet Muenchen
// Boltzmannstr. 3, 85748 Garching b. Muenchen, Germany
//
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
// except in compliance with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions
// and limitations under the License.
//
// ================================================================================================
#include "particleflowrenderer.h"
#include "tgt/buffer.h"
#include "tgt/tgt_math.h"
#include "tgt/logmanager.h"
#include "tgt/shadermanager.h"
#include "tgt/textureunit.h"
#include "tgt/vertexarrayobject.h"
#include "core/classification/geometry1dtransferfunction.h"
#include "core/classification/tfgeometry1d.h"
#include "core/datastructures/imagedata.h"
#include "core/datastructures/imagerepresentationgl.h"
#include "core/datastructures/lightsourcedata.h"
#include "core/datastructures/geometrydatafactory.h"
#include "core/datastructures/renderdata.h"
namespace
campvis
{
static
const
GenericOption
<
ParticleFlowRenderer
::
ColoringMode
>
coloringModeOptions
[
3
]
=
{
GenericOption
<
ParticleFlowRenderer
::
ColoringMode
>
(
"age"
,
"Coloring by Age"
,
ParticleFlowRenderer
::
COLORING_AGE
),
GenericOption
<
ParticleFlowRenderer
::
ColoringMode
>
(
"velocity"
,
"Coloring by Velocity"
,
ParticleFlowRenderer
::
COLORING_VELOCITY
),
GenericOption
<
ParticleFlowRenderer
::
ColoringMode
>
(
"direction"
,
"Coloring by Direction"
,
ParticleFlowRenderer
::
COLORING_DIRECTION
)
};
const
std
::
string
ParticleFlowRenderer
::
loggerCat_
=
"CAMPVis.modules.classification.ParticleFlowRenderer"
;
ParticleFlowRenderer
::
ParticleFlowRenderer
(
IVec2Property
*
viewportSizeProp
)
:
VisualizationProcessor
(
viewportSizeProp
)
,
p_resetButton
(
"ResetButton"
,
"Reset"
)
,
p_inputVectors
(
"InputImage"
,
"Input Image Vectors"
,
"vectors"
,
DataNameProperty
::
READ
)
,
p_renderOutput
(
"RenderOutput"
,
"Output Image"
,
"ParticleFlowRenderer.output"
,
DataNameProperty
::
WRITE
)
,
p_lenThresholdMin
(
"LenThresholdMin"
,
"Length Threshold Min"
,
.001
f
,
0.
f
,
1000.
f
,
0.005
f
)
,
p_lenThresholdMax
(
"LenThresholdMax"
,
"Length Threshold Max"
,
10.
f
,
0.
f
,
10000.
f
,
10.
f
)
,
p_numParticles
(
"NumParticles"
,
"Number of Particles"
,
2048
,
32
,
65536
)
,
p_lifetime
(
"Lifetime"
,
"Particle Lifetime"
,
10.
f
,
1.
f
,
100.
f
,
1.
f
,
1
)
,
p_flowProfile1
(
"FlowSpline1"
,
"Flow Profile - Spline 1"
,
1.
f
,
.0
f
,
2.
f
)
,
p_flowProfile2
(
"FlowSpline2"
,
"Flow Profile - Spline 2"
,
1.
f
,
.0
f
,
2.
f
)
,
p_flowProfile3
(
"FlowSpline3"
,
"Flow Profile - Spline 3"
,
1.
f
,
.0
f
,
2.
f
)
,
p_flowProfile4
(
"FlowSpline4"
,
"Flow Profile - Spline 4"
,
1.
f
,
.0
f
,
2.
f
)
,
p_Time
(
"time"
,
"Time"
,
0
,
0
,
100
)
,
p_pointSize
(
"PointSize"
,
"Point Size"
,
4
,
1
,
16
)
,
p_coloring
(
"Coloring"
,
"Color Scheme"
,
coloringModeOptions
,
3
)
,
p_transferFunction
(
"TransferFunction"
,
"Coloring Transfer Function"
,
new
Geometry1DTransferFunction
(
256
))
,
p_enableShading
(
"EnableShading"
,
"Enable Shading"
,
true
)
,
p_lightId
(
"LightId"
,
"Input Light Source"
,
"lightsource"
,
DataNameProperty
::
READ
)
,
p_camera
(
"Camera"
,
"Camera"
,
tgt
::
Camera
())
,
_shader
(
nullptr
)
,
_positionBufferA
(
nullptr
)
,
_positionBufferB
(
nullptr
)
,
_velocityBufferA
(
nullptr
)
,
_velocityBufferB
(
nullptr
)
,
_startTimeBufferA
(
nullptr
)
,
_startTimeBufferB
(
nullptr
)
,
_initialPositionBuffer
(
nullptr
)
,
_vaoA
(
nullptr
)
,
_vaoB
(
nullptr
)
{
addProperty
(
p_resetButton
,
INVALID_PROPERTIES
);
addProperty
(
p_Time
,
INVALID_RESULT
|
FIRST_FREE_TO_USE_INVALIDATION_LEVEL
);
addProperty
(
p_inputVectors
,
INVALID_RESULT
|
INVALID_PROPERTIES
);
addProperty
(
p_renderOutput
);
addProperty
(
p_lenThresholdMin
);
addProperty
(
p_lenThresholdMax
);
addProperty
(
p_numParticles
);
addProperty
(
p_lifetime
);
addProperty
(
p_camera
);
addProperty
(
p_flowProfile1
);
addProperty
(
p_flowProfile2
);
addProperty
(
p_flowProfile3
);
addProperty
(
p_flowProfile4
);
addProperty
(
p_pointSize
);
addProperty
(
p_coloring
);
addProperty
(
p_transferFunction
);
addProperty
(
p_enableShading
,
INVALID_RESULT
|
INVALID_PROPERTIES
|
INVALID_SHADER
);
addProperty
(
p_lightId
);
static_cast
<
Geometry1DTransferFunction
*>
(
p_transferFunction
.
getTF
())
->
addGeometry
(
TFGeometry1D
::
createHeatedBodyColorMap
());
}
ParticleFlowRenderer
::~
ParticleFlowRenderer
()
{
}
void
ParticleFlowRenderer
::
init
()
{
VisualizationProcessor
::
init
();
_shader
=
ShdrMgr
.
loadWithCustomGlslVersion
(
"modules/vectorfield/glsl/particleflowrenderer.vert"
,
""
,
"modules/vectorfield/glsl/particleflowrenderer.frag"
,
generateGlslHeader
(),
"400"
);
const
char
*
outputNames
[]
=
{
"ex_Position"
,
"ex_Velocity"
,
"ex_StartTime"
};
glTransformFeedbackVaryings
(
_shader
->
getID
(),
3
,
outputNames
,
GL_SEPARATE_ATTRIBS
);
_shader
->
linkProgram
();
tgtAssert
(
_shader
->
isLinked
(),
"Shader not linked!"
);
LGL_ERROR
;
}
void
ParticleFlowRenderer
::
deinit
()
{
ShdrMgr
.
dispose
(
_shader
);
delete
_positionBufferA
;
delete
_positionBufferB
;
delete
_velocityBufferA
;
delete
_velocityBufferB
;
delete
_startTimeBufferA
;
delete
_startTimeBufferB
;
delete
_initialPositionBuffer
;
delete
_vaoA
;
delete
_vaoB
;
VisualizationProcessor
::
deinit
();
}
void
ParticleFlowRenderer
::
updateResult
(
DataContainer
&
dataContainer
)
{
const
float
frameLength
=
0.1
f
;
if
(
_initialPositionBuffer
==
0
)
{
LERROR
(
"Transform-Feedback buffers not initialized."
);
return
;
}
ImageRepresentationGL
::
ScopedRepresentation
vectors
(
dataContainer
,
p_inputVectors
.
getValue
());
if
(
vectors
)
{
ScopedTypedData
<
LightSourceData
>
light
(
dataContainer
,
p_lightId
.
getValue
());
if
(
p_enableShading
.
getValue
()
==
false
||
light
!=
nullptr
)
{
const
tgt
::
Camera
&
cam
=
p_camera
.
getValue
();
float
scale
=
getTemporalFlowScaling
((
float
)
p_Time
.
getValue
()
/
100.
f
,
p_flowProfile1
.
getValue
(),
p_flowProfile2
.
getValue
(),
p_flowProfile3
.
getValue
(),
p_flowProfile4
.
getValue
());
glEnable
(
GL_DEPTH_TEST
);
_shader
->
activate
();
_shader
->
setUniform
(
"_projectionMatrix"
,
cam
.
getProjectionMatrix
());
_shader
->
setUniform
(
"_viewMatrix"
,
cam
.
getViewMatrix
());
_shader
->
setUniform
(
"_modelMatrix"
,
vectors
->
getParent
()
->
getMappingInformation
().
getVoxelToWorldMatrix
());
_shader
->
setUniform
(
"_scale"
,
scale
);
_shader
->
setUniform
(
"_threshold"
,
tgt
::
vec2
(
p_lenThresholdMin
.
getValue
(),
p_lenThresholdMax
.
getValue
()));
if
(
p_enableShading
.
getValue
()
&&
light
!=
nullptr
)
{
light
->
bind
(
_shader
,
"_lightSource"
);
}
if
(
getInvalidationLevel
()
&
FIRST_FREE_TO_USE_INVALIDATION_LEVEL
)
{
// stage 1: perform 1 step of particle simulation
_shader
->
selectSubroutine
(
tgt
::
ShaderObject
::
VERTEX_SHADER
,
"update"
);
_shader
->
setUniform
(
"_time"
,
_currentTime
);
_shader
->
setUniform
(
"_frameLength"
,
frameLength
);
_shader
->
setUniform
(
"_lifetime"
,
p_lifetime
.
getValue
());
tgt
::
TextureUnit
flowUnit
;
vectors
->
bind
(
_shader
,
flowUnit
,
"_volume"
,
"_volumeTextureParams"
);
glEnable
(
GL_RASTERIZER_DISCARD
);
glBindTransformFeedback
(
GL_TRANSFORM_FEEDBACK
,
_feedback
[
_drawBuffer
]);
glBeginTransformFeedback
(
GL_POINTS
);
glBindVertexArray
((
_drawBuffer
==
1
)
?
_vaoA
->
getId
()
:
_vaoB
->
getId
());
glDrawArrays
(
GL_POINTS
,
0
,
_numParticles
);
glEndTransformFeedback
();
glBindTransformFeedback
(
GL_TRANSFORM_FEEDBACK
,
0
);
glDisable
(
GL_RASTERIZER_DISCARD
);
_drawBuffer
=
1
-
_drawBuffer
;
_currentTime
+=
frameLength
;
validate
(
FIRST_FREE_TO_USE_INVALIDATION_LEVEL
);
LGL_ERROR
;
}