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
Compare Revisions
35d262dba70f4cc645eeb39101c38b8464badae6...17c2b8767470626870b7395ea3c17b92964aad24
Source
17c2b8767470626870b7395ea3c17b92964aad24
Select Git revision
...
Target
35d262dba70f4cc645eeb39101c38b8464badae6
Select Git revision
Compare
Commits (4)
Basic files for Visualization assignment
· eb24cfdd
Jakob Weiss
authored
Dec 15, 2017
eb24cfdd
Minor fix to allow simplified linking to application-lib
· 53e27972
Jakob Weiss
authored
Dec 15, 2017
53e27972
Changed names of template file
· 73afddbe
Jakob Weiss
authored
Dec 15, 2017
73afddbe
Merge branch 'cppcourse-ws17' into 'cppcourse-ws17'
· 17c2b876
Jakob Weiss
authored
Dec 15, 2017
Cppcourse ws17 See merge request
!8
17c2b876
Show whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
1001 additions
and
0 deletions
+1001
-0
application/CMakeLists.txt
application/CMakeLists.txt
+2
-0
modules/cppcourse/cppcourse.cmake
modules/cppcourse/cppcourse.cmake
+37
-0
modules/cppcourse/cppcourse.cpp
modules/cppcourse/cppcourse.cpp
+13
-0
modules/cppcourse/glsl/verysimpleraycaster.frag
modules/cppcourse/glsl/verysimpleraycaster.frag
+144
-0
modules/cppcourse/pipelines/cppcoursepipeline.cpp
modules/cppcourse/pipelines/cppcoursepipeline.cpp
+3
-0
modules/cppcourse/pipelines/cppcoursepipeline.h
modules/cppcourse/pipelines/cppcoursepipeline.h
+3
-0
modules/cppcourse/processors/EDFhandler.cpp
modules/cppcourse/processors/EDFhandler.cpp
+233
-0
modules/cppcourse/processors/EDFhandler.h
modules/cppcourse/processors/EDFhandler.h
+33
-0
modules/cppcourse/processors/IOutilities.h
modules/cppcourse/processors/IOutilities.h
+313
-0
modules/cppcourse/processors/verysimpleraycaster.cpp
modules/cppcourse/processors/verysimpleraycaster.cpp
+102
-0
modules/cppcourse/processors/verysimpleraycaster.h
modules/cppcourse/processors/verysimpleraycaster.h
+60
-0
modules/cppcourse/processors/volume.cpp
modules/cppcourse/processors/volume.cpp
+29
-0
modules/cppcourse/processors/volume.h
modules/cppcourse/processors/volume.h
+29
-0
No files found.
application/CMakeLists.txt
View file @
17c2b876
...
...
@@ -128,6 +128,8 @@ TARGET_LINK_LIBRARIES(campvis-application-lib ${CampvisMainLibs} ${CampvisGlobal
# the code to export DLL symbols
SET_TARGET_PROPERTIES
(
campvis-application-lib PROPERTIES DEFINE_SYMBOL
"CAMPVIS_APPLICATION_BUILD_DLL"
)
target_compile_definitions
(
campvis-application-lib PUBLIC
${
CampvisGlobalDefinitions
}
${
CampvisModulesDefinitions
}
${
CampvisApplicationDefinitions
}
)
target_include_directories
(
campvis-application-lib PUBLIC
${
CampvisGlobalIncludeDirs
}
${
CampvisModulesIncludeDirs
}
)
IF
(
CAMPVIS_GROUP_SOURCE_FILES
)
DEFINE_SOURCE_GROUPS_FROM_SUBDIR
(
CampvisApplicationSources
${
CampvisHome
}
""
)
...
...
modules/cppcourse/cppcourse.cmake
0 → 100644
View file @
17c2b876
# modules/cppcourse/cppcourse.cmake
# CMake file for the Module for the Cpp Course in WS 17
# Set module status (valid values are STABLE, TESTING and EXPERIMENTAL)
SET
(
ThisModStatus EXPERIMENTAL
)
# Set whether this module has external dependencies that are not shipped with CAMPVis.
SET
(
ThisModExternalDependencies TRUE
)
# The files and assignments need only to be parsed if the module is enabled
IF
(
ModuleEnabled
)
# Source files:
FILE
(
GLOB ThisModSources RELATIVE
${
ModulesDir
}
modules/cppcourse/pipelines/*.cpp
modules/cppcourse/processors/*.cpp
modules/cppcourse/datastructures/*.cpp
modules/cppcourse/properties/*.cpp
modules/cppcourse/*.cpp
)
# Header files (including GLSL files so that they'll appear in VS projects)
FILE
(
GLOB ThisModHeaders RELATIVE
${
ModulesDir
}
modules/cppcourse/glsl/*.frag
modules/cppcourse/glsl/*.geom
modules/cppcourse/glsl/*.vert
modules/cppcourse/pipelines/*.h
modules/cppcourse/processors/*.h
modules/cppcourse/datastructures/*.h
modules/cppcourse/properties/*.h
)
# Define the GLSL shader path, so that all needed shaders will be deployed to target directory
SET
(
ThisModShaderDirectories
"modules/cppcourse/glsl"
)
# Define dependency modules (the pipelines in the vis modules use processors from io)
#SET(ThisModDependencies io)
ENDIF
(
ModuleEnabled
)
modules/cppcourse/cppcourse.cpp
0 → 100644
View file @
17c2b876
#include "core/pipeline/pipelinefactory.h"
#include "core/pipeline/processorfactory.h"
#include "modules/cppcourse/pipelines/cppcoursepipeline.h"
#include "modules/cppcourse/processors/verysimpleraycaster.h"
namespace
campvis
{
// explicitly instantiate templates to register the pipelines to make them available in the prototyping GUI
//template class PipelineRegistrar<CPPCoursePipeline>;
template
class
SmartProcessorRegistrar
<
VerySimpleRaycaster
>;
}
modules/cppcourse/glsl/verysimpleraycaster.frag
0 → 100644
View file @
17c2b876
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012-2015, 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.
//
// ================================================================================================
layout
(
location
=
0
)
out
vec4
FragData0
;
///< outgoing fragment color
#include "tools/gradient.frag"
#include "tools/raycasting.frag"
#include "tools/shading.frag"
#include "tools/texture2d.frag"
#include "tools/texture3d.frag"
#include "tools/transferfunction.frag"
uniform
vec2
_viewportSizeRCP
;
uniform
float
_jitterStepSizeMultiplier
;
// ray entry points
uniform
sampler2D
_entryPoints
;
uniform
sampler2D
_entryPointsDepth
;
uniform
TextureParameters2D
_entryParams
;
// ray exit points
uniform
sampler2D
_exitPoints
;
uniform
sampler2D
_exitPointsDepth
;
uniform
TextureParameters2D
_exitParams
;
// DVR volume
uniform
sampler3D
_volume
;
uniform
TextureParameters3D
_volumeTextureParams
;
// Transfer function
uniform
sampler1D
_transferFunction
;
uniform
TFParameters1D
_transferFunctionParams
;
uniform
LightSource
_lightSource
;
uniform
vec3
_cameraPosition
;
uniform
float
_samplingStepSize
;
const
float
SAMPLING_BASE_INTERVAL_RCP
=
200
.
0
;
// The compositing mode that gets passed through from the p_compositingMode property
uniform
int
_compositingMode
;
/**
* Performs the raycasting and returns the final fragment color.
*/
vec4
performRaycasting
(
in
vec3
entryPoint
,
in
vec3
exitPoint
,
in
vec2
texCoords
)
{
vec4
result
=
vec4
(
0
.
0
);
float
firstHitT
=
-
1
.
0
;
// calculate ray start and endpoint
vec3
direction
=
exitPoint
.
rgb
-
entryPoint
.
rgb
;
float
t
=
0
.
0
;
float
tend
=
length
(
direction
);
direction
=
normalize
(
direction
);
// This applies a small random offset to avoid banding artifacts
// Uncomment to see the effect ;)
jitterEntryPoint
(
entryPoint
,
direction
,
_samplingStepSize
*
_jitterStepSizeMultiplier
);
while
(
t
<
tend
)
{
// compute sample position - next step
vec3
samplePosition
=
entryPoint
.
rgb
+
t
*
direction
;
// get the intensity of our sample from the volume
float
intensity
=
texture
(
_volume
,
samplePosition
).
r
;
// use the transfer function to transform from
vec4
color
=
lookupTF
(
_transferFunction
,
_transferFunctionParams
,
intensity
);
if
(
_compositingMode
==
0
)
{
// accomodate for variable sampling rates
color
.
a
=
1
.
0
-
pow
(
1
.
0
-
color
.
a
,
_samplingStepSize
*
SAMPLING_BASE_INTERVAL_RCP
);
// perform compositing
// Alpha-blend the new sample with the color accumulated so far
blendUnder
(
result
,
color
);
}
else
if
(
_compositingMode
==
1
)
{
//TODO
result
=
vec4
(
entryPoint
,
1
.
0
);
}
// else if...
// save first hit ray parameter for depth value calculation
if
(
firstHitT
<
0
.
0
&&
result
.
a
>
0
.
0
)
{
firstHitT
=
t
;
}
// advance to the next evaluation point along the ray
t
+=
_samplingStepSize
;
}
// calculate depth value from ray parameter
gl_FragDepth
=
1
.
0
;
if
(
firstHitT
>=
0
.
0
)
{
float
depthEntry
=
texture
(
_entryPointsDepth
,
texCoords
).
z
;
float
depthExit
=
texture
(
_exitPointsDepth
,
texCoords
).
z
;
gl_FragDepth
=
calculateDepthValue
(
firstHitT
/
tend
,
depthEntry
,
depthExit
);
}
return
result
;
}
/***
* The main method.
***/
void
main
()
{
vec2
p
=
gl_FragCoord
.
xy
*
_viewportSizeRCP
;
vec3
frontPos
=
texture
(
_entryPoints
,
p
).
rgb
;
vec3
backPos
=
texture
(
_exitPoints
,
p
).
rgb
;
//determine whether the ray has to be casted
if
(
frontPos
==
backPos
)
{
//background needs no raycasting
discard
;
}
else
{
//fragCoords are lying inside the boundingbox
FragData0
=
performRaycasting
(
frontPos
,
backPos
,
p
);
}
}
modules/cppcourse/pipelines/cppcoursepipeline.cpp
0 → 100644
View file @
17c2b876
#include "cppcoursepipeline.h"
// TODO
modules/cppcourse/pipelines/cppcoursepipeline.h
0 → 100644
View file @
17c2b876
#pragma once
// TODO
modules/cppcourse/processors/EDFhandler.cpp
0 → 100644
View file @
17c2b876
#include "EDFhandler.h"
#include <fstream>
#include <map>
#include <exception>
#include "IOutilities.h"
Volume
EDFHandler
::
read
(
const
std
::
string
&
filename
)
{
// open the file
std
::
ifstream
file
(
filename
,
std
::
ios
::
binary
);
if
(
!
file
.
good
())
throw
std
::
invalid_argument
(
"EDFHandler::read: error opening "
+
filename
+
" for reading"
);
// read a single character and make sure that a header is opened
if
(
file
.
eof
()
||
file
.
get
()
!=
'{'
)
throw
std
::
invalid_argument
(
"EDFHandler::read: failed reading header opening marker"
);
std
::
map
<
std
::
string
,
std
::
string
>
attributes
;
// --- read header data
while
(
!
file
.
eof
())
{
// skip whitespace
while
(
!
file
.
eof
())
{
const
int
chr
=
file
.
peek
();
if
(
chr
!=
'\r'
&&
chr
!=
'\n'
&&
chr
!=
' '
&&
chr
!=
'\t'
)
break
;
file
.
ignore
(
1
);
}
// abort if the header is closed
if
(
file
.
eof
()
||
file
.
peek
()
==
'}'
)
break
;
// extract the attribute assignment
bool
quotesSingle
=
false
,
quotesDouble
=
false
;
std
::
string
assignment
=
""
;
while
(
!
file
.
eof
())
{
const
int
chr
=
file
.
get
();
// abort on end-of-assignment
if
(
chr
==
';'
&&
!
(
quotesSingle
||
quotesDouble
))
break
;
// check for quote characters
if
(
chr
==
'\''
)
quotesSingle
=
!
quotesSingle
;
if
(
chr
==
'\"'
)
quotesDouble
=
!
quotesDouble
;
assignment
+=
chr
;
}
// split the assignment, and remove quotes (if they exist)
auto
delim
=
assignment
.
find
(
'='
);
if
(
delim
==
std
::
string
::
npos
)
throw
std
::
invalid_argument
(
"EDFHandler::read: failed reading name/value delimiter"
);
std
::
string
name
=
assignment
.
substr
(
0
,
delim
);
StringUtils
::
trim
(
name
);
std
::
string
value
=
assignment
.
substr
(
delim
+
1
);
StringUtils
::
trim
(
value
);
if
(
value
[
0
]
==
value
[
value
.
size
()
-
1
]
&&
(
value
[
0
]
==
'\''
||
value
[
0
]
==
'\"'
))
value
=
value
.
substr
(
1
,
value
.
size
()
-
2
);
StringUtils
::
tolower
(
name
);
attributes
[
name
]
=
value
;
}
file
.
ignore
(
2
);
// end of header marker
// --- now parse the header data
// read the dimensions
std
::
vector
<
int
>
dim
;
for
(
int
i
=
1
;
;
++
i
)
{
// assemble the attribute name
std
::
stringstream
aux
;
aux
<<
"dim_"
<<
i
;
// try to find the attribute
auto
dimIt
=
attributes
.
find
(
aux
.
str
());
if
(
dimIt
==
attributes
.
end
())
break
;
dim
.
push_back
(
StringUtils
::
parseString
<
int
>
(
dimIt
->
second
));
}
const
int
nDims
=
dim
.
size
();
if
(
!
nDims
)
throw
std
::
runtime_error
(
"EDFHandler::read: dimension information not found"
);
// parse the (non-standard) spacing tag
std
::
vector
<
float
>
spacing
;
auto
spacingIt
=
attributes
.
find
(
"spacing"
);
if
(
spacingIt
!=
attributes
.
end
())
StringUtils
::
parseString
<
float
>
(
spacingIt
->
second
,
spacing
);
// check for a byte order tag, but fall back to the default value
ByteOrder
::
ByteOrderEnum
byteorder
=
ByteOrder
::
DEFAULT
;
auto
byteorderIt
=
attributes
.
find
(
"byteorder"
);
if
(
byteorderIt
!=
attributes
.
end
())
{
std
::
string
byteorderValue
=
byteorderIt
->
second
;
StringUtils
::
tolower
(
byteorderValue
);
if
(
byteorderValue
==
"highbytefirst"
)
byteorder
=
ByteOrder
::
HIGH_BYTE_FIRST
;
else
if
(
byteorderValue
==
"lowbytefirst"
)
byteorder
=
ByteOrder
::
LOW_BYTE_FIRST
;
else
throw
std
::
runtime_error
(
"invalid byte order value"
);
}
// check for the 'element type' value
DataTypes
::
DataTypeEnum
datatype
;
auto
datatypeIt
=
attributes
.
find
(
"datatype"
);
if
(
datatypeIt
!=
attributes
.
end
())
{
std
::
string
datatypeValue
=
datatypeIt
->
second
;
StringUtils
::
tolower
(
datatypeValue
);
if
(
datatypeValue
==
"signedbyte"
)
datatype
=
DataTypes
::
INT8
;
else
if
(
datatypeValue
==
"unsignedbyte"
)
datatype
=
DataTypes
::
UINT8
;
else
if
(
datatypeValue
==
"signedshort"
)
datatype
=
DataTypes
::
INT16
;
else
if
(
datatypeValue
==
"unsignedshort"
)
datatype
=
DataTypes
::
UINT16
;
else
if
(
datatypeValue
==
"float"
||
datatypeValue
==
"floatvalue"
||
datatypeValue
==
"real"
)
datatype
=
DataTypes
::
FLOAT32
;
else
if
(
datatypeValue
==
"double"
||
datatypeValue
==
"doublevalue"
)
datatype
=
DataTypes
::
FLOAT64
;
// todo: add further data types
else
throw
std
::
runtime_error
(
"EDFHandler::read: invalid/unsupported data type"
);
}
else
throw
std
::
runtime_error
(
"EDFHandler::read: data type not found"
);
auto
compressionIt
=
attributes
.
find
(
"compression"
);
if
(
compressionIt
!=
attributes
.
end
())
throw
std
::
runtime_error
(
"compression not supported"
);
int
size
=
0
;
auto
sizeIt
=
attributes
.
find
(
"size"
);
if
(
sizeIt
!=
attributes
.
end
())
size
=
StringUtils
::
parseString
<
int
>
(
sizeIt
->
second
);
auto
imageIt
=
attributes
.
find
(
"image"
);
if
(
imageIt
!=
attributes
.
end
()
&&
StringUtils
::
parseString
<
int
>
(
imageIt
->
second
)
!=
1
)
throw
std
::
runtime_error
(
"EDFHandler::read: image not set to 1"
);
// convert size
Eigen
::
VectorXi
dimSizes
(
nDims
);
for
(
int
i
=
0
;
i
<
nDims
;
++
i
)
dimSizes
[
i
]
=
dim
[
i
];
if
(
dimSizes
.
prod
()
*
DataTypes
::
getSizeForType
(
datatype
)
!=
size
)
throw
std
::
runtime_error
(
"EDFHandler::read: size inconsistency"
);
// convert spacing
Eigen
::
VectorXf
dimSpacing
=
Eigen
::
VectorXf
::
Ones
(
nDims
);
if
(
spacing
.
size
()
>
0
)
{
if
(
spacing
.
size
()
!=
nDims
)
throw
std
::
runtime_error
(
"EDFHandler::read: spacing inconsistency"
);
for
(
int
i
=
0
;
i
<
nDims
;
++
i
)
dimSpacing
[
i
]
=
spacing
[
i
];
}
// compute the byte shuffling flag
const
bool
byteShuffle
=
(
byteorder
!=
ByteOrder
::
DEFAULT
);
// --- read in the image data
Eigen
::
VectorXf
data
=
DataTypes
::
parseData
<
float
>
(
file
,
datatype
,
dimSizes
.
prod
(),
byteShuffle
);
file
.
close
();
// --- setup the volume
Eigen
::
Vector3f
lowerLeft
=
Eigen
::
Vector3f
::
Zero
();
Eigen
::
Vector3f
upperRight
=
lowerLeft
+
(
dimSizes
.
cast
<
float
>
().
array
()
*
dimSpacing
.
array
()
).
matrix
();
Volume
vol
(
lowerLeft
,
upperRight
,
dimSpacing
);
vol
.
setContent
(
data
);
return
vol
;
}
void
EDFHandler
::
write
(
const
std
::
string
&
filename
,
const
Volume
&
vol
)
{
// open the EDF file
std
::
ofstream
file
(
filename
,
std
::
ios
::
binary
);
if
(
!
file
.
good
())
throw
std
::
invalid_argument
(
"EDFHandler::write: cannot open "
+
filename
+
" for writing"
);
// open the header
file
<<
"{
\n
"
;
file
<<
"HeaderID = EH:000001:000000:000000;
\n
"
;
file
<<
"Image = "
<<
1
<<
";
\n
"
;
if
(
ByteOrder
::
DEFAULT
==
ByteOrder
::
HIGH_BYTE_FIRST
)
file
<<
"ByteOrder = HighByteFirst;
\n
"
;
else
file
<<
"ByteOrder = LowByteFirst;
\n
"
;
file
<<
"DataType = "
<<
TYPE_FLOAT
<<
";
\n
"
;
// write dimension and size
for
(
int
i
=
0
;
i
<
3
;
++
i
)
file
<<
"Dim_"
<<
(
i
+
1
)
<<
" = "
<<
vol
.
getNumVoxels
()[
i
]
<<
";
\n
"
;
file
<<
"Size = "
<<
vol
.
getNumVoxels
().
prod
()
*
sizeof
(
float
)
<<
";
\n
"
;
// write spacing
file
<<
"Spacing ="
;
for
(
int
i
=
0
;
i
<
3
;
++
i
)
file
<<
' '
<<
vol
.
getSpacing
()[
i
];
file
<<
";
\n
"
;
// pad the header by adding spaces such that the header ends on a kilobyte boundary
std
::
size_t
n
=
1024
;
while
(
n
<
(
static_cast
<
std
::
size_t
>
(
file
.
tellp
())
+
3
))
n
+=
1024
;
n
-=
static_cast
<
std
::
size_t
>
(
file
.
tellp
())
+
3
;
while
(
n
>
0
)
{
file
.
put
(
' '
);
n
--
;
}
// close the header
file
<<
"
\n
}
\n
"
;
// write the volume data
file
.
write
(
reinterpret_cast
<
const
char
*>
(
vol
.
getContent
().
data
()),
vol
.
getNumVoxels
().
prod
()
*
sizeof
(
float
)
);
file
.
close
();
}
modules/cppcourse/processors/EDFhandler.h
0 → 100644
View file @
17c2b876
#ifndef EDFHANDLER_H
#define EDFHANDLER_H
#include <string>
#include "volume.h"
/**
* \brief EDFHandler reads and writes EDF files.
*/
class
EDFHandler
{
public:
/* \brief read an EDF file into a Volume
* \param[in] filename - filename of the EDF file to be read
* \return volume containing the data
*/
static
Volume
read
(
const
std
::
string
&
filename
);
/* \brief write out a Volume into an EDF file
* \param[in] filename - filename of the EDF file to be written
* \param[in] vol - volume to be written
*/
static
void
write
(
const
std
::
string
&
filename
,
const
Volume
&
vol
);
private:
static
constexpr
auto
TYPE_FLOAT
=
"FloatValue"
;
};
#endif // EDFHANDLER_H
modules/cppcourse/processors/IOutilities.h
0 → 100644
View file @
17c2b876
#ifndef IOUTILITIES_H
#define IOUTILITIES_H
#include <algorithm>
#include <regex>
#include <string>
#include <vector>
#include <Eigen/Dense>
/**
* \brief StringUtils provides common string utilities for file parsing.
*/
struct
StringUtils
{
/* \brief remove whitespace at front and back of string
* \param[in,out] str - string to be trimmed
*/
static
void
trim
(
std
::
string
&
str
);
/* \brief convert string to lower case
* \param[in,out] str - string to be converted
*/
static
void
tolower
(
std
::
string
&
str
);
/* \brief convert string to upper case
* \param[in,out] str - string to be converted
*/
static
void
toupper
(
std
::
string
&
str
);
/* \brief convert string to arbitrary datatype using stringstream
* \param[in] str - string to be converted
* \return converted datatype
*/
template
<
typename
Type
>
static
Type
parseString
(
const
std
::
string
&
str
);
/* \brief convert string to vector of arbitrary data type using stringstream
* \param[in] str - string to be converted
* \param[out] vec - vector of converted datatypes
* \return number of converted datatypes
*/
template
<
typename
Type
>
static
int
parseString
(
const
std
::
string
&
str
,
std
::
vector
<
Type
>&
vec
);
};
/**
* \brief ByteOrder supplies helper routines to cope with byte order conversions.
*/
struct
ByteOrder
{
/// byte order enum
enum
ByteOrderEnum
{
LOW_BYTE_FIRST
,
// little endian (e.g. x86)
HIGH_BYTE_FIRST
// big endian (e.g. PowerPC)
};
/// attempt to determine endianness (works on Mac at least..), default to little endian
static
const
ByteOrderEnum
DEFAULT
=
#if defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN
HIGH_BYTE_FIRST
;
#else
LOW_BYTE_FIRST
;
#endif
/* \brief shuffle the bytes of the data pointed to by ptr to switch endianness
* \tparam _DataType - data type underlying the pointer
* \param[in,out] ptr - pointer to the data
* \param[in] elements - number of elements of _DataType
*/
template
<
typename
_DataType
>
static
void
shuffleBytes
(
void
*
ptr
,
long
elements
);
};
/**
* \brief DataTypes supplies helper enums and routines for type conversions.
*/
struct
DataTypes
{
/// data type enum
enum
DataTypeEnum
{
INT8
,
UINT8
,
INT16
,
UINT16
,
INT32
,
UINT32
,
FLOAT32
,
FLOAT64
};
/* \brief return the size in bytes for the specified data type
* \param[in] dataType - type for which to return the size in bytes
* \return size of dataType in bytes
*/
static
int
getSizeForType
(
const
DataTypeEnum
&
dataType
);
/* \brief parse data of type dataType from stream in into an Eigen::Vector
* (dispatches to parseData<_DataType, _Scalar> internally)
* \tparam _Scalar - scalar type of Eigen::Vector to return
* \param[in] in - stream from which to read
* \param[in] dataType - dataType of elements to be read from stream
* \param[in] sizeInElements - number of elements (of type dataType) to read from stream
* \param[in] shuffleBytes - flag whether to shuffle bytes around to account for endianness change
* \return vector of _Scalar containing the read in values
*/
template
<
typename
_Scalar
>
static
Eigen
::
Matrix
<
_Scalar
,
Eigen
::
Dynamic
,
1
>
parseData
(
std
::
istream
&
in
,
const
DataTypeEnum
&
dataType
,
long
sizeInElements
,
bool
shuffleBytes
);
private:
/* \brief parse data of type _DataType from stream in into an Eigen::Vector
* \tparam _DataType - data type of elements to be read from stream
* \tparam _Scalar - scalar type of Eigen::Vector to return
* \param[in] in - stream from which to read
* \param[in] sizeInElements - number of elements (of type _DataType) to read from stream
* \param[in] shuffleBytes - flag whether to shuffle bytes around to account for endianness change
* \return vector of _Scalar containing the read in values
*/
template
<
typename
_DataType
,
typename
_Scalar
>
static
Eigen
::
Matrix
<
_Scalar
,
Eigen
::
Dynamic
,
1
>
parseData
(
std
::
istream
&
in
,
long
sizeInElements
,
bool
shuffleBytes
);
};
// --------- Implementations -----------
inline
void
StringUtils
::
trim
(
std
::
string
&
str
)
{
str
=
std
::
regex_replace
(
str
,
std
::
regex
(
"^
\\
s+|
\\
s+$"
),
std
::
string
(
""
));
}
inline
void
StringUtils
::
tolower
(
std
::
string
&
str
)
{
std
::
transform
(
str
.
begin
(),
str
.
end
(),
str
.
begin
(),
::
tolower
);
}
inline
void
StringUtils
::
toupper
(
std
::
string
&
str
)
{
std
::
transform
(
str
.
begin
(),
str
.
end
(),
str
.
begin
(),
::
toupper
);
}
template
<
typename
Type
>
inline
Type
StringUtils
::
parseString
(
const
std
::
string
&
str
)
{
Type
value
;
std
::
stringstream
convert
(
str
);
convert
>>
value
;
if
(
convert
.
fail
()
)
throw
std
::
runtime_error
(
"parseString: string conversion failed"
);
return
value
;
}
template
<
typename
Type
>
inline
int
StringUtils
::
parseString
(
const
std
::
string
&
str
,
std
::
vector
<
Type
>&
vec
)
{
int
count
=
0
;
Type
value
;
std
::
stringstream
convert
(
str
);
while
(
!
convert
.
eof
())
{
convert
>>
value
;
if
(
convert
.
fail
())
throw
std
::
runtime_error
(
"parseString: string conversion failed"
);
vec
.
push_back
(
value
);
count
++
;
}
return
count
;
}
template
<
>
inline
void
ByteOrder
::
shuffleBytes
<
uint8_t
>
(
void
*
ptr
,
long
elements
)
{}
template
<
>
inline
void
ByteOrder
::
shuffleBytes
<
int8_t
>
(
void
*
ptr
,
long
elements
)
{}
template
<
>
inline
void
ByteOrder
::
shuffleBytes
<
uint16_t
>
(
void
*
ptr
,
long
elements
)
{
uint16_t
*
ptr16
=
static_cast
<
uint16_t
*>
(
ptr
);
for
(
long
index
=
0
;
index
<
elements
;
++
index
)
ptr16
[
index
]
=
((
ptr16
[
index
]
&
0xff
)
<<
8
)
|
((
ptr16
[
index
]
&
0xff00
)
>>
8
);
}
template
<
>
inline
void
ByteOrder
::
shuffleBytes
<
int16_t
>
(
void
*
ptr
,
long
elements
)
{
shuffleBytes
<
uint16_t
>
(
ptr
,
elements
);
}
template
<
>
inline
void
ByteOrder
::
shuffleBytes
<
uint32_t
>
(
void
*
ptr
,
long
elements
)
{
uint32_t
*
ptr32
=
static_cast
<
uint32_t
*>
(
ptr
);
for
(
long
index
=
0
;
index
<
elements
;
++
index
)
#ifdef _MSC_VER // dumb version for stupid compilers
ptr32
[
index
]
=
((
ptr32
[
index
]
&
0xff
)
<<
24
)
|
((
ptr32
[
index
]
&
0xff00
)
<<
8
)
|
((
ptr32
[
index
]
&
0xff0000
)
>>
8
)
|
((
ptr32
[
index
]
&
0xff000000
)
>>
24
);
#else
ptr32
[
index
]
=
__builtin_bswap32
(
ptr32
[
index
]);
#endif
}
template
<
>
inline
void
ByteOrder
::
shuffleBytes
<
int32_t
>
(
void
*
ptr
,
long
elements
)
{
shuffleBytes
<
uint32_t
>
(
ptr
,
elements
);
}
template
<
>
inline
void
ByteOrder
::
shuffleBytes
<
float
>
(
void
*
ptr
,
long
elements
)
{
shuffleBytes
<
uint32_t
>
(
ptr
,
elements
);
}
template
<
>
inline
void
ByteOrder
::
shuffleBytes
<
double
>
(
void
*
ptr
,
long
elements
)
{
uint64_t
*
ptr64
=
static_cast
<
uint64_t
*>
(
ptr
);
for
(
long
index
=
0
;
index
<
elements
;
++
index
)
#ifdef _MSC_VER // dumb version for stupid compilers
ptr64
[
index
]
=
((
ptr64
[
index
]
&
0xffl
)
<<
56l
)
|
((
ptr64
[
index
]
&
0xff00l
)
<<
40l
)
|
((
ptr64
[
index
]
&
0xff0000l
)
<<
24l
)
|
((
ptr64
[
index
]
&
0xff000000l
)
<<
8l
)
|
((
ptr64
[
index
]
&
0xff00000000l
)
>>
8l
)
|
((
ptr64
[
index
]
&
0xff0000000000l
)
>>
24l
)
|
((
ptr64
[
index
]
&
0xff000000000000l
)
<<
40l
)
|
((
ptr64
[
index
]
&
0xff00000000000000l
)
>>
56l
);
#else
ptr64
[
index
]
=
__builtin_bswap64
(
ptr64
[
index
]);
#endif
}
inline
int
DataTypes
::
getSizeForType
(
const
DataTypeEnum
&
dataType
)
{
switch
(
dataType
)
{
case
INT8
:
case
UINT8
:
return
1
;
case
INT16
:
case
UINT16
:
return
2
;
case
INT32
:
case
UINT32
:
case
FLOAT32
:
return
4
;
case
FLOAT64
:
return
8
;
default:
throw
std
::
invalid_argument
(
"getSizeForType: unsupported data type."
);
}
}
template
<
typename
_Scalar
>
inline
Eigen
::
Matrix
<
_Scalar
,
Eigen
::
Dynamic
,
1
>
DataTypes
::
parseData
(
std
::
istream
&
in
,
const
DataTypeEnum
&
dataType
,
long
sizeInElements
,
bool
shuffleBytes
)
{
switch
(
dataType
)
{
case
UINT8
:
return
parseData
<
uint8_t
,
_Scalar
>
(
in
,
sizeInElements
,
shuffleBytes
);
case
INT8
:
return
parseData
<
int8_t
,
_Scalar
>
(
in
,
sizeInElements
,
shuffleBytes
);
case
UINT16
:
return
parseData
<
uint16_t
,
_Scalar
>
(
in
,
sizeInElements
,
shuffleBytes
);
case
INT16
:
return
parseData
<
int16_t
,
_Scalar
>
(
in
,
sizeInElements
,
shuffleBytes
);
case
UINT32
:
return
parseData
<
uint32_t
,
_Scalar
>
(
in
,
sizeInElements
,
shuffleBytes
);
case
INT32
:
return
parseData
<
int32_t
,
_Scalar
>
(
in
,
sizeInElements
,
shuffleBytes
);
case
FLOAT32
:
return
parseData
<
float
,
_Scalar
>
(
in
,
sizeInElements
,
shuffleBytes
);
case
FLOAT64
:
return
parseData
<
double
,
_Scalar
>
(
in
,
sizeInElements
,
shuffleBytes
);
default:
throw
std
::
runtime_error
(
"parseData: unsupported data type."
);
}
}
template
<
typename
_DataType
,
typename
_Scalar
>
inline
Eigen
::
Matrix
<
_Scalar
,
Eigen
::
Dynamic
,
1
>
DataTypes
::
parseData
(
std
::
istream
&
in
,
long
sizeInElements
,
bool
shuffleBytes
)
{
long
sizeInBytes
=
sizeInElements
*
sizeof
(
_DataType
);
// parse data into temporary buffer
std
::
vector
<
_DataType
>
tempBuffer
(
sizeInElements
);
in
.
read
(
reinterpret_cast
<
char
*>
(
&
tempBuffer
[
0
]),
sizeInBytes
);
if
(
in
.
gcount
()
!=
sizeInBytes
)
throw
std
::
runtime_error
(
"parseData: failed to read the expected amount of data."
);
// perform byte shuffling to correct endianness
if
(
shuffleBytes
)
ByteOrder
::
shuffleBytes
<
_DataType
>
(
&
tempBuffer
[
0
],
sizeInElements
);
// create result vector
Eigen
::
Matrix
<
_Scalar
,
Eigen
::
Dynamic
,
1
>
result
(
sizeInElements
);
for
(
long
i
=
0
;
i
<
sizeInElements
;
++
i
)
result
(
i
)
=
static_cast
<
_Scalar
>
(
tempBuffer
[
i
]);
return
result
;
}
#endif // IOUTILITIES_H
modules/cppcourse/processors/verysimpleraycaster.cpp
0 → 100644
View file @
17c2b876
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012-2015, 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 "verysimpleraycaster.h"
#include "core/tools/quadrenderer.h"
#include "core/datastructures/lightsourcedata.h"
#include "core/datastructures/cameradata.h"
#include "core/datastructures/renderdata.h"
#include "core/datastructures/genericimagerepresentationlocal.h"
#include "core/datastructures/facegeometry.h"
#include "core/pipeline/processordecoratorgradient.h"
#include <tbb/tbb.h>
namespace
campvis
{
const
std
::
string
VerySimpleRaycaster
::
loggerCat_
=
"CAMPVis.modules.cppcourse.VerySimpleRaycaster"
;
VerySimpleRaycaster
::
VerySimpleRaycaster
(
IVec2Property
*
viewportSizeProp
)
:
RaycastingProcessor
(
viewportSizeProp
,
"modules/cppcourse/glsl/verysimpleraycaster.frag"
,
true
)
,
p_compositingMode
(
"CompositingMode"
,
"Compositing Mode"
,
0
,
0
,
3
)
{
addProperty
(
p_compositingMode
);
}
VerySimpleRaycaster
::~
VerySimpleRaycaster
()
{
}
void
VerySimpleRaycaster
::
init
()
{
RaycastingProcessor
::
init
();
}
void
VerySimpleRaycaster
::
deinit
()
{
RaycastingProcessor
::
deinit
();
}
void
VerySimpleRaycaster
::
processImpl
(
DataContainer
&
data
,
ImageRepresentationGL
::
ScopedRepresentation
&
image
)
{
// acquire handles to the data inside the container
ScopedTypedData
<
RenderData
,
true
>
outputImage
(
data
,
p_targetImageID
.
getValue
(),
true
);
if
(
image
)
{
FramebufferActivationGuard
fag
(
this
);
// allocate the color and depth buffer for rendering
createAndAttachTexture
(
GL_RGBA8
,
&
outputImage
);
createAndAttachDepthTexture
(
&
outputImage
);
// define a color buffer for output
static
const
GLenum
buffers
[]
=
{
GL_COLOR_ATTACHMENT0
};
glDrawBuffers
(
1
,
buffers
);
// apply some rendering parameters
glEnable
(
GL_DEPTH_TEST
);
glClear
(
GL_COLOR_BUFFER_BIT
|
GL_DEPTH_BUFFER_BIT
);
// read the property value and pass it to the GPU shader
_shader
->
setUniform
(
"_compositingMode"
,
p_compositingMode
.
getValue
());
// render a screen-filling quad to perform the raycasting
QuadRdr
.
renderQuad
();
// restore OpenGL state
glDrawBuffers
(
1
,
buffers
);
glDisable
(
GL_DEPTH_TEST
);
LGL_ERROR
;
// Put the rendered image into the data container
data
.
addData
(
p_targetImageID
.
getValue
(),
new
RenderData
(
_fbo
));
}
else
{
LDEBUG
(
"Could not load light source from DataContainer."
);
}
}
std
::
string
VerySimpleRaycaster
::
generateHeader
()
const
{
std
::
string
toReturn
=
RaycastingProcessor
::
generateHeader
();
return
toReturn
;
}
}
modules/cppcourse/processors/verysimpleraycaster.h
0 → 100644
View file @
17c2b876
#pragma once
#include "core/pipeline/raycastingprocessor.h"
#include "modules/modulesapi.h"
#include <string>
namespace
cgt
{
class
Shader
;
}
namespace
campvis
{
/**
* Simplified volume raycasting
*/
class
CAMPVIS_MODULES_API
VerySimpleRaycaster
:
public
RaycastingProcessor
{
public:
/**
* Constructs a new VerySimpleRaycaster Processor
**/
explicit
VerySimpleRaycaster
(
IVec2Property
*
viewportSizeProp
);
/**
* Destructor
**/
virtual
~
VerySimpleRaycaster
();
/**
* To be used in ProcessorFactory static methods
*/
static
const
std
::
string
getId
()
{
return
"VerySimpleRaycaster"
;
};
/// \see AbstractProcessor::getName()
virtual
const
std
::
string
getName
()
const
{
return
getId
();
};
/// \see AbstractProcessor::getDescription()
virtual
const
std
::
string
getDescription
()
const
{
return
"Greatly simplified raycaster for experimentation."
;
};
/// \see AbstractProcessor::getAuthor()
virtual
const
std
::
string
getAuthor
()
const
{
return
"Jakob Weiss <jakob.weiss@tum.de>"
;
};
/// \see AbstractProcessor::getProcessorState()
virtual
ProcessorState
getProcessorState
()
const
{
return
AbstractProcessor
::
EXPERIMENTAL
;
};
// Property to control the compositing mode of the shader
IntProperty
p_compositingMode
;
/// \see AbstractProcessor::init
virtual
void
init
();
/// \see AbstractProcessor::deinit
virtual
void
deinit
();
protected:
/// \see RaycastingProcessor::processImpl()
virtual
void
processImpl
(
DataContainer
&
data
,
ImageRepresentationGL
::
ScopedRepresentation
&
image
);
/// \see RaycastingProcessor::generateHeader()
virtual
std
::
string
generateHeader
()
const
;
static
const
std
::
string
loggerCat_
;
};
}
modules/cppcourse/processors/volume.cpp
0 → 100644
View file @
17c2b876
#include "volume.h"
Volume
::
Volume
(
Eigen
::
Vector3f
lowerLeft
,
Eigen
::
Vector3f
upperRight
,
Eigen
::
Vector3f
spacing
)
:
boundingBox
(
Eigen
::
AlignedBox3f
(
lowerLeft
,
upperRight
)),
spacing
(
spacing
)
{}
Eigen
::
AlignedBox3f
Volume
::
getBoundingBox
()
const
{
return
boundingBox
;
}
Eigen
::
Vector3f
Volume
::
getSpacing
()
const
{
return
spacing
;
}
Eigen
::
Vector3i
Volume
::
getNumVoxels
()
const
{
Eigen
::
Vector3f
sizes
=
boundingBox
.
sizes
();
Eigen
::
Vector3i
numVoxels
;
for
(
int
i
=
0
;
i
<
3
;
i
++
)
{
numVoxels
[
i
]
=
ceil
(
sizes
[
i
]
/
spacing
[
i
]);
}
return
numVoxels
;
}
Eigen
::
VectorXf
Volume
::
getContent
()
const
{
return
content
;
}
void
Volume
::
setContent
(
const
Eigen
::
VectorXf
&
c
)
{
content
=
c
;
}
modules/cppcourse/processors/volume.h
0 → 100644
View file @
17c2b876
#ifndef VOLUME_H
#define VOLUME_H
#include <Eigen/Geometry>
#include <string>
class
Volume
{
public:
Volume
(
Eigen
::
Vector3f
lowerLeft
,
Eigen
::
Vector3f
upperRight
,
Eigen
::
Vector3f
sp
);
Eigen
::
AlignedBox3f
getBoundingBox
()
const
;
Eigen
::
Vector3f
getSpacing
()
const
;
Eigen
::
Vector3i
getNumVoxels
()
const
;
Eigen
::
VectorXf
getContent
()
const
;
void
setContent
(
const
Eigen
::
VectorXf
&
c
);
// ... other useful methods ...
private:
Eigen
::
AlignedBox3f
boundingBox
;
Eigen
::
Vector3f
spacing
;
Eigen
::
VectorXf
content
;
};
#endif // VOLUME_H