Initial Commit

This commit is contained in:
hodasemi 2018-05-17 15:50:03 +02:00
commit ea6ebaa070
879 changed files with 252132 additions and 0 deletions

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
*.so
framework/bin/

31
.vscode/launch.json vendored Normal file
View file

@ -0,0 +1,31 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Launch",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/framework/bin/unix/cgv_viewer",
"args": [
"plugin:cg_fltk.cgv",
"plugin:CGII.cgv"
],
"additionalSOLibSearchPath": "${workspaceFolder}/CGII/build/cmake/build/bin/unix/",
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": true,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true,
}
]
}
]
}

6
.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,6 @@
{
"C_Cpp.default.includePath": [
"CGII/src/",
"framework/include/"
]
}

24
.vscode/tasks.json vendored Normal file
View file

@ -0,0 +1,24 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "Run CG-Viewer",
"type": "shell",
"command": "LD_LIBRARY_PATH=$LD_LIBRARY_PATH:CGII/build/cmake/build/bin/unix/ framework/bin/unix/./cgv_viewer plugin:cg_fltk.cgv plugin:CGII.cgv",
"problemMatcher": []
},
{
"label": "Build All",
"type": "shell",
"command": "cd framework && sh buildLinux.sh"
},
{
"label": "Build CGII",
"type": "shell",
"command": "cd CGII/build/cmake && make clean && cmake . && make -j16",
"problemMatcher": []
}
]
}

BIN
02_Skelettdarstellung.pdf Normal file

Binary file not shown.

View file

@ -0,0 +1,57 @@
cmake_minimum_required(VERSION 2.8)
project(CGII)
# Use shared libraries
set(BUILD_SHARED_LIBS 1)
# Set the default build type to be release
if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release")
endif()
# Needed cgv packages
find_package(cgv COMPONENTS gui render math
PATHS "${CMAKE_CURRENT_SOURCE_DIR}/../../../framework/cmake")
# Needed cgv libraries
find_package(cgv_gl)
# A viewer shall be created
find_package(cgv_viewer)
# Create the plugin
cgv_add_module(CGII
../../src/Animation.cpp
../../src/AtomicTransform.cpp
../../src/Bone.cpp
../../src/CGVDemo.cpp
../../src/DataStore.cpp
../../src/IHasBoundingBox.cpp
../../src/IKViewer.cpp
../../src/Mesh.cpp
../../src/Skeleton.cpp
../../src/SkeletonViewer.cpp
../../src/SkinnedMeshViewer.cpp
../../src/main.cpp)
# Set include directories
include_directories(
.
${cgv_INCLUDE_DIRS}
${cgv_gl_INCLUDE_DIRS}
)
target_link_libraries(CGII ${cgv_LIBRARIES} ${cgv_gl_LIBRARIES})
# Set the viewer working directory to point at the
# the source files
# Add a viewer
cgv_add_viewer(launch-exercise1
CGII
cg_fltk
crg_stereo_view)

View file

@ -0,0 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2015
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CGII", "CGII.vcxproj", "{B3512B24-AD4C-4928-A8F3-0961BCA02819}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{B3512B24-AD4C-4928-A8F3-0961BCA02819}.Debug|Win32.ActiveCfg = Debug|Win32
{B3512B24-AD4C-4928-A8F3-0961BCA02819}.Debug|Win32.Build.0 = Debug|Win32
{B3512B24-AD4C-4928-A8F3-0961BCA02819}.Release|Win32.ActiveCfg = Release|Win32
{B3512B24-AD4C-4928-A8F3-0961BCA02819}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View file

@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{B3512B24-AD4C-4928-A8F3-0961BCA02819}</ProjectGuid>
<RootNamespace>exercise1</RootNamespace>
<ProjectName>CGII</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<TargetExt>.dll</TargetExt>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<TargetExt>.dll</TargetExt>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>../../../framework/include;../../../framework/include/libs;../../../framework/include/libs/GLEW;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;_UNICODE;UNICODE;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>../../../framework/vs2015/lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>cgv_gui_d14.lib;cgv_render_d14.lib;cgv_math_d14.lib;cgv_gl_d14.lib;cgv_media_d14.lib;cgv_base_d14.lib;cgv_data_d14.lib;cgv_reflect_d14.lib;cgv_signal_d14.lib;cgv_type_d14.lib;cgv_utils_d14.lib;GLEW_d14.lib;glu32.lib;opengl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>../../../framework/include;../../../framework/include/libs;../../../framework/include/libs/GLEW;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_WINDOWS;_UNICODE;UNICODE;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>false</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>../../../framework/vs2015/lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>cgv_gui_14.lib;cgv_render_14.lib;cgv_math_14.lib;cgv_gl_14.lib;cgv_media_14.lib;cgv_base_14.lib;cgv_data_14.lib;cgv_reflect_14.lib;cgv_signal_14.lib;cgv_type_14.lib;cgv_utils_14.lib;GLEW_14.lib;glu32.lib;opengl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\src\Animation.cpp" />
<ClCompile Include="..\..\src\AtomicTransform.cpp" />
<ClCompile Include="..\..\src\Bone.cpp" />
<ClCompile Include="..\..\src\CGVDemo.cpp" />
<ClCompile Include="..\..\src\DataStore.cpp" />
<ClCompile Include="..\..\src\IHasBoundingBox.cpp" />
<ClCompile Include="..\..\src\IKViewer.cpp" />
<ClCompile Include="..\..\src\main.cpp" />
<ClCompile Include="..\..\src\Mesh.cpp" />
<ClCompile Include="..\..\src\SkinnedMeshViewer.cpp" />
<ClCompile Include="..\..\src\Skeleton.cpp" />
<ClCompile Include="..\..\src\SkeletonViewer.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\Animation.h" />
<ClInclude Include="..\..\src\AnimationFrameBone.h" />
<ClInclude Include="..\..\src\AtomicTransform.h" />
<ClInclude Include="..\..\src\Bone.h" />
<ClInclude Include="..\..\src\CGVDemo.h" />
<ClInclude Include="..\..\src\common.h" />
<ClInclude Include="..\..\src\DataStore.h" />
<ClInclude Include="..\..\src\IHasBoundingBox.h" />
<ClInclude Include="..\..\src\IKViewer.h" />
<ClInclude Include="..\..\src\math_helper.h" />
<ClInclude Include="..\..\src\Mesh.h" />
<ClInclude Include="..\..\src\SkinnedMeshViewer.h" />
<ClInclude Include="..\..\src\Skeleton.h" />
<ClInclude Include="..\..\src\SkeletonViewer.h" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\glsl\skinning.glfs" />
<None Include="..\..\glsl\skinning.glgs" />
<None Include="..\..\glsl\skinning.glvs" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -0,0 +1,103 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="..\..\src\Skeleton.cpp">
<Filter>Data</Filter>
</ClCompile>
<ClCompile Include="..\..\src\Mesh.cpp">
<Filter>Data</Filter>
</ClCompile>
<ClCompile Include="..\..\src\SkeletonViewer.cpp">
<Filter>GUI</Filter>
</ClCompile>
<ClCompile Include="..\..\src\CGVDemo.cpp">
<Filter>GUI</Filter>
</ClCompile>
<ClCompile Include="..\..\src\main.cpp" />
<ClCompile Include="..\..\src\SkinnedMeshViewer.cpp">
<Filter>GUI</Filter>
</ClCompile>
<ClCompile Include="..\..\src\DataStore.cpp">
<Filter>Data</Filter>
</ClCompile>
<ClCompile Include="..\..\src\Bone.cpp">
<Filter>Data</Filter>
</ClCompile>
<ClCompile Include="..\..\src\IHasBoundingBox.cpp">
<Filter>Data</Filter>
</ClCompile>
<ClCompile Include="..\..\src\AtomicTransform.cpp">
<Filter>Data</Filter>
</ClCompile>
<ClCompile Include="..\..\src\IKViewer.cpp">
<Filter>GUI</Filter>
</ClCompile>
<ClCompile Include="..\..\src\Animation.cpp">
<Filter>Data</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Filter Include="Data">
<UniqueIdentifier>{bf6a7e83-64db-4f6f-bf19-2c59ea6141c4}</UniqueIdentifier>
</Filter>
<Filter Include="GUI">
<UniqueIdentifier>{66ec743a-37f4-4b15-bc3f-3e460dfca223}</UniqueIdentifier>
</Filter>
<Filter Include="Shader">
<UniqueIdentifier>{caa3ae7b-2442-49d3-a105-8661977e64f3}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\Skeleton.h">
<Filter>Data</Filter>
</ClInclude>
<ClInclude Include="..\..\src\Mesh.h">
<Filter>Data</Filter>
</ClInclude>
<ClInclude Include="..\..\src\CGVDemo.h">
<Filter>GUI</Filter>
</ClInclude>
<ClInclude Include="..\..\src\common.h" />
<ClInclude Include="..\..\src\DataStore.h">
<Filter>Data</Filter>
</ClInclude>
<ClInclude Include="..\..\src\SkeletonViewer.h">
<Filter>GUI</Filter>
</ClInclude>
<ClInclude Include="..\..\src\SkinnedMeshViewer.h">
<Filter>GUI</Filter>
</ClInclude>
<ClInclude Include="..\..\src\Bone.h">
<Filter>Data</Filter>
</ClInclude>
<ClInclude Include="..\..\src\IHasBoundingBox.h">
<Filter>Data</Filter>
</ClInclude>
<ClInclude Include="..\..\src\AtomicTransform.h">
<Filter>Data</Filter>
</ClInclude>
<ClInclude Include="..\..\src\IKViewer.h">
<Filter>GUI</Filter>
</ClInclude>
<ClInclude Include="..\..\src\math_helper.h">
<Filter>Data</Filter>
</ClInclude>
<ClInclude Include="..\..\src\Animation.h">
<Filter>Data</Filter>
</ClInclude>
<ClInclude Include="..\..\src\AnimationFrameBone.h">
<Filter>Data</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\..\glsl\skinning.glgs">
<Filter>Shader</Filter>
</None>
<None Include="..\..\glsl\skinning.glvs">
<Filter>Shader</Filter>
</None>
<None Include="..\..\glsl\skinning.glfs">
<Filter>Shader</Filter>
</None>
</ItemGroup>
</Project>

View file

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LocalDebuggerCommand>$(ProjectDir)../../../framework/vs2015/bin/cgv_viewer_d14.exe</LocalDebuggerCommand>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
<LocalDebuggerCommandArguments>plugin:"../framework/vs2015/lib/cg_fltk_d14.dll" plugin:"../framework/vs2015/lib/crg_stereo_view_d14.dll" plugin:"build/vs2015/Debug/CGII.dll"</LocalDebuggerCommandArguments>
<LocalDebuggerWorkingDirectory>$(ProjectDir)../../</LocalDebuggerWorkingDirectory>
<LocalDebuggerEnvironment>PATH=.;..\framework\vs2015\lib;%PATH% $(LocalDebuggerEnvironment)</LocalDebuggerEnvironment>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LocalDebuggerCommand>$(ProjectDir)../../../framework/vs2015/bin/cgv_viewer_14.exe</LocalDebuggerCommand>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
<LocalDebuggerCommandArguments>plugin:"../framework/vs2015/lib/cg_fltk_14.dll" plugin:"../framework/vs2015/lib/crg_stereo_view_14.dll" plugin:"build/vs2015/Release/CGII.dll"</LocalDebuggerCommandArguments>
<LocalDebuggerWorkingDirectory>$(ProjectDir)../../</LocalDebuggerWorkingDirectory>
<LocalDebuggerEnvironment>PATH=.;..\framework\vs2015\lib;%PATH% $(LocalDebuggerEnvironment)</LocalDebuggerEnvironment>
</PropertyGroup>
</Project>

View file

@ -0,0 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2017
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CGII", "CGII.vcxproj", "{B3512B24-AD4C-4928-A8F3-0961BCA02819}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{B3512B24-AD4C-4928-A8F3-0961BCA02819}.Debug|Win32.ActiveCfg = Debug|Win32
{B3512B24-AD4C-4928-A8F3-0961BCA02819}.Debug|Win32.Build.0 = Debug|Win32
{B3512B24-AD4C-4928-A8F3-0961BCA02819}.Release|Win32.ActiveCfg = Release|Win32
{B3512B24-AD4C-4928-A8F3-0961BCA02819}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View file

@ -0,0 +1,118 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{B3512B24-AD4C-4928-A8F3-0961BCA02819}</ProjectGuid>
<RootNamespace>exercise1</RootNamespace>
<ProjectName>CGII</ProjectName>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<TargetExt>.dll</TargetExt>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<TargetExt>.dll</TargetExt>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>../../../framework/include;../../../framework/include/libs;../../../framework/include/libs/GLEW;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;_UNICODE;UNICODE;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>../../../framework/vs2017/lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>cgv_gui_d141.lib;cgv_render_d141.lib;cgv_math_d141.lib;cgv_gl_d141.lib;cgv_media_d141.lib;cgv_base_d141.lib;cgv_data_d141.lib;cgv_reflect_d141.lib;cgv_signal_d141.lib;cgv_type_d141.lib;cgv_utils_d141.lib;GLEW_d141.lib;glu32.lib;opengl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>../../../framework/include;../../../framework/include/libs;../../../framework/include/libs/GLEW;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_WINDOWS;_UNICODE;UNICODE;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>false</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>../../../framework/vs2017/lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>cgv_gui_141.lib;cgv_render_141.lib;cgv_math_141.lib;cgv_gl_141.lib;cgv_media_141.lib;cgv_base_141.lib;cgv_data_141.lib;cgv_reflect_141.lib;cgv_signal_141.lib;cgv_type_141.lib;cgv_utils_141.lib;GLEW_141.lib;glu32.lib;opengl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\src\Animation.cpp" />
<ClCompile Include="..\..\src\AtomicTransform.cpp" />
<ClCompile Include="..\..\src\Bone.cpp" />
<ClCompile Include="..\..\src\CGVDemo.cpp" />
<ClCompile Include="..\..\src\DataStore.cpp" />
<ClCompile Include="..\..\src\IHasBoundingBox.cpp" />
<ClCompile Include="..\..\src\IKViewer.cpp" />
<ClCompile Include="..\..\src\main.cpp" />
<ClCompile Include="..\..\src\Mesh.cpp" />
<ClCompile Include="..\..\src\SkinnedMeshViewer.cpp" />
<ClCompile Include="..\..\src\Skeleton.cpp" />
<ClCompile Include="..\..\src\SkeletonViewer.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\Animation.h" />
<ClInclude Include="..\..\src\AnimationFrameBone.h" />
<ClInclude Include="..\..\src\AtomicTransform.h" />
<ClInclude Include="..\..\src\Bone.h" />
<ClInclude Include="..\..\src\CGVDemo.h" />
<ClInclude Include="..\..\src\common.h" />
<ClInclude Include="..\..\src\DataStore.h" />
<ClInclude Include="..\..\src\IHasBoundingBox.h" />
<ClInclude Include="..\..\src\IKViewer.h" />
<ClInclude Include="..\..\src\math_helper.h" />
<ClInclude Include="..\..\src\Mesh.h" />
<ClInclude Include="..\..\src\SkinnedMeshViewer.h" />
<ClInclude Include="..\..\src\Skeleton.h" />
<ClInclude Include="..\..\src\SkeletonViewer.h" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\glsl\skinning.glfs" />
<None Include="..\..\glsl\skinning.glgs" />
<None Include="..\..\glsl\skinning.glvs" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -0,0 +1,103 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="..\..\src\Skeleton.cpp">
<Filter>Data</Filter>
</ClCompile>
<ClCompile Include="..\..\src\Mesh.cpp">
<Filter>Data</Filter>
</ClCompile>
<ClCompile Include="..\..\src\SkeletonViewer.cpp">
<Filter>GUI</Filter>
</ClCompile>
<ClCompile Include="..\..\src\CGVDemo.cpp">
<Filter>GUI</Filter>
</ClCompile>
<ClCompile Include="..\..\src\main.cpp" />
<ClCompile Include="..\..\src\SkinnedMeshViewer.cpp">
<Filter>GUI</Filter>
</ClCompile>
<ClCompile Include="..\..\src\DataStore.cpp">
<Filter>Data</Filter>
</ClCompile>
<ClCompile Include="..\..\src\Bone.cpp">
<Filter>Data</Filter>
</ClCompile>
<ClCompile Include="..\..\src\IHasBoundingBox.cpp">
<Filter>Data</Filter>
</ClCompile>
<ClCompile Include="..\..\src\AtomicTransform.cpp">
<Filter>Data</Filter>
</ClCompile>
<ClCompile Include="..\..\src\IKViewer.cpp">
<Filter>GUI</Filter>
</ClCompile>
<ClCompile Include="..\..\src\Animation.cpp">
<Filter>Data</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Filter Include="Data">
<UniqueIdentifier>{bf6a7e83-64db-4f6f-bf19-2c59ea6141c4}</UniqueIdentifier>
</Filter>
<Filter Include="GUI">
<UniqueIdentifier>{66ec743a-37f4-4b15-bc3f-3e460dfca223}</UniqueIdentifier>
</Filter>
<Filter Include="Shader">
<UniqueIdentifier>{caa3ae7b-2442-49d3-a105-8661977e64f3}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\Skeleton.h">
<Filter>Data</Filter>
</ClInclude>
<ClInclude Include="..\..\src\Mesh.h">
<Filter>Data</Filter>
</ClInclude>
<ClInclude Include="..\..\src\CGVDemo.h">
<Filter>GUI</Filter>
</ClInclude>
<ClInclude Include="..\..\src\common.h" />
<ClInclude Include="..\..\src\DataStore.h">
<Filter>Data</Filter>
</ClInclude>
<ClInclude Include="..\..\src\SkeletonViewer.h">
<Filter>GUI</Filter>
</ClInclude>
<ClInclude Include="..\..\src\SkinnedMeshViewer.h">
<Filter>GUI</Filter>
</ClInclude>
<ClInclude Include="..\..\src\Bone.h">
<Filter>Data</Filter>
</ClInclude>
<ClInclude Include="..\..\src\IHasBoundingBox.h">
<Filter>Data</Filter>
</ClInclude>
<ClInclude Include="..\..\src\AtomicTransform.h">
<Filter>Data</Filter>
</ClInclude>
<ClInclude Include="..\..\src\IKViewer.h">
<Filter>GUI</Filter>
</ClInclude>
<ClInclude Include="..\..\src\math_helper.h">
<Filter>Data</Filter>
</ClInclude>
<ClInclude Include="..\..\src\Animation.h">
<Filter>Data</Filter>
</ClInclude>
<ClInclude Include="..\..\src\AnimationFrameBone.h">
<Filter>Data</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\..\glsl\skinning.glgs">
<Filter>Shader</Filter>
</None>
<None Include="..\..\glsl\skinning.glvs">
<Filter>Shader</Filter>
</None>
<None Include="..\..\glsl\skinning.glfs">
<Filter>Shader</Filter>
</None>
</ItemGroup>
</Project>

View file

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LocalDebuggerCommand>$(ProjectDir)../../../framework/vs2017/bin/cgv_viewer_d141.exe</LocalDebuggerCommand>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
<LocalDebuggerCommandArguments>plugin:"../framework/vs2017/lib/cg_fltk_d141.dll" plugin:"../framework/vs2017/lib/crg_stereo_view_d141.dll" plugin:"build/vs2017/Debug/CGII.dll"</LocalDebuggerCommandArguments>
<LocalDebuggerWorkingDirectory>$(ProjectDir)../../</LocalDebuggerWorkingDirectory>
<LocalDebuggerEnvironment>PATH=.;..\framework\vs2017\lib;%PATH% $(LocalDebuggerEnvironment)</LocalDebuggerEnvironment>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LocalDebuggerCommand>$(ProjectDir)../../../framework/vs2017/bin/cgv_viewer_141.exe</LocalDebuggerCommand>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
<LocalDebuggerCommandArguments>plugin:"../framework/vs2017/lib/cg_fltk_141.dll" plugin:"../framework/vs2017/lib/crg_stereo_view_141.dll" plugin:"build/vs2017/Release/CGII.dll"</LocalDebuggerCommandArguments>
<LocalDebuggerWorkingDirectory>$(ProjectDir)../../</LocalDebuggerWorkingDirectory>
<LocalDebuggerEnvironment>PATH=.;..\framework\vs2017\lib;%PATH% $(LocalDebuggerEnvironment)</LocalDebuggerEnvironment>
</PropertyGroup>
</Project>

82533
CGII/data/jump.amc Normal file

File diff suppressed because it is too large Load diff

338
CGII/data/jump.asf Normal file
View file

@ -0,0 +1,338 @@
# AST/ASF file generated using VICON BodyLanguage
# -----------------------------------------------
:version 1.10
:name VICON
:units
mass 1.0
length 0.45
angle deg
:documentation
.ast/.asf automatically generated from VICON data using
VICON BodyBuilder and BodyLanguage model FoxedUp or BRILLIANT.MOD
:root
order TX TY TZ RX RY RZ
axis XYZ
position 0 0 0
orientation 0 0 0
:bonedata
begin
id 1
name lhipjoint
direction 0.566809 -0.746272 0.349008
length 2.40479
axis 0 0 0 XYZ
end
begin
id 2
name lfemur
direction 0.34202 -0.939693 0
length 7.1578
axis 0 0 20 XYZ
dof rx ry rz
limits (-160.0 20.0)
(-70.0 70.0)
(-60.0 70.0)
end
begin
id 3
name ltibia
direction 0.34202 -0.939693 0
length 7.49137
axis 0 0 20 XYZ
dof rx
limits (-10.0 170.0)
end
begin
id 4
name lfoot
direction 0.0665746 -0.182912 0.980873
length 2.36784
axis -90 7.62852e-016 20 XYZ
dof rx rz
limits (-45.0 90.0)
(-70.0 20.0)
end
begin
id 5
name ltoes
direction 1.53601e-011 -4.22058e-011 1
length 1.18966
axis -90 7.62852e-016 20 XYZ
dof rx
limits (-90.0 20.0)
end
begin
id 6
name rhipjoint
direction -0.550236 -0.756381 0.353735
length 2.37265
axis 0 0 0 XYZ
end
begin
id 7
name rfemur
direction -0.34202 -0.939693 0
length 7.43386
axis 0 0 -20 XYZ
dof rx ry rz
limits (-160.0 20.0)
(-70.0 70.0)
(-70.0 60.0)
end
begin
id 8
name rtibia
direction -0.34202 -0.939693 0
length 7.50908
axis 0 0 -20 XYZ
dof rx
limits (-10.0 170.0)
end
begin
id 9
name rfoot
direction -0.0683029 -0.187661 0.979856
length 2.41173
axis -90 -7.62852e-016 -20 XYZ
dof rx rz
limits (-45.0 90.0)
(-20.0 70.0)
end
begin
id 10
name rtoes
direction -1.53528e-011 -4.21968e-011 1
length 1.21082
axis -90 -7.62852e-016 -20 XYZ
dof rx
limits (-90.0 20.0)
end
begin
id 11
name lowerback
direction 0.013823 0.995423 -0.0945635
length 2.04495
axis 0 0 0 XYZ
dof rx ry rz
limits (-20.0 45.0)
(-30.0 30.0)
(-30.0 30.0)
end
begin
id 12
name upperback
direction 0.0276657 0.9994 -0.020853
length 2.05008
axis 0 0 0 XYZ
dof rx ry rz
limits (-20.0 45.0)
(-30.0 30.0)
(-30.0 30.0)
end
begin
id 13
name thorax
direction 0.019782 0.999531 0.0233827
length 2.06488
axis 0 0 0 XYZ
dof rx ry rz
limits (-20.0 45.0)
(-30.0 30.0)
(-30.0 30.0)
end
begin
id 14
name lowerneck
direction -0.0308541 0.994709 0.0979874
length 1.75553
axis 0 0 0 XYZ
dof rx ry rz
limits (-20.0 45.0)
(-30.0 30.0)
(-30.0 30.0)
end
begin
id 15
name upperneck
direction 0.0588398 0.995804 -0.0700903
length 1.76878
axis 0 0 0 XYZ
dof rx ry rz
limits (-20.0 45.0)
(-30.0 30.0)
(-30.0 30.0)
end
begin
id 16
name head
direction 0.0209966 0.999159 -0.0352225
length 1.77193
axis 0 0 0 XYZ
dof rx ry rz
limits (-20.0 45.0)
(-30.0 30.0)
(-30.0 30.0)
end
begin
id 17
name lclavicle
direction 0.938182 0.335073 -0.0868338
length 3.58396
axis 0 0 0 XYZ
dof ry rz
limits (-20.0 10.0)
(0.0 20.0)
end
begin
id 18
name lhumerus
direction 1 -4.48971e-011 -1.26313e-017
length 4.983
axis 180 -30 -90 XYZ
dof rx ry rz
limits (-60.0 90.0)
(-90.0 90.0)
(-90.0 90.0)
end
begin
id 19
name lradius
direction 1 -4.48948e-011 -5.89033e-027
length 3.48356
axis 180 -30 -90 XYZ
dof rx
limits (-10.0 170.0)
end
begin
id 20
name lwrist
direction 1 -4.48977e-011 -1.48983e-026
length 1.74178
axis 9.0955e-015 90 90 XYZ
dof ry
limits (-180.0 0.0)
end
begin
id 21
name lhand
direction 1 -4.49046e-011 -2.98066e-026
length 0.715259
axis 1.90115e-014 90 90 XYZ
dof rx rz
limits (-90.0 90.0)
(-45.0 45.0)
end
begin
id 22
name lfingers
direction 1 -4.48907e-011 -5.95731e-026
length 0.576661
axis 3.80223e-014 90 90 XYZ
dof rx
limits (0.0 90.0)
end
begin
id 23
name lthumb
direction 0.707107 -6.34963e-011 0.707107
length 0.827973
axis -90 45 -3.84942e-014 XYZ
dof rx rz
limits (-45.0 45.0)
(-45.0 45.0)
end
begin
id 24
name rclavicle
direction -0.909637 0.398485 -0.11735
length 3.44819
axis 0 0 0 XYZ
dof ry rz
limits (-10.0 20.0)
(-20.0 0.0)
end
begin
id 25
name rhumerus
direction -1 -4.48978e-011 -1.09333e-027
length 5.2419
axis 180 30 90 XYZ
dof rx ry rz
limits (-90.0 60.0)
(-90.0 90.0)
(-90.0 90.0)
end
begin
id 26
name rradius
direction -1 -4.48953e-011 -7.61841e-027
length 3.44417
axis 180 30 90 XYZ
dof rx
limits (-10.0 170.0)
end
begin
id 27
name rwrist
direction -1 -4.48977e-011 -1.48983e-026
length 1.72209
axis 9.0955e-015 -90 -90 XYZ
dof ry
limits (-180.0 0.0)
end
begin
id 28
name rhand
direction -1 -4.49027e-011 -2.98038e-026
length 0.622529
axis 1.90115e-014 -90 -90 XYZ
dof rx rz
limits (-90.0 90.0)
(-45.0 45.0)
end
begin
id 29
name rfingers
direction -1 -4.48838e-011 -5.95531e-026
length 0.501899
axis 3.80223e-014 -90 -90 XYZ
dof rx
limits (0.0 90.0)
end
begin
id 30
name rthumb
direction -0.707107 -6.34937e-011 0.707107
length 0.720629
axis -90 -45 3.84942e-014 XYZ
dof rx rz
limits (-45.0 45.0)
(-45.0 45.0)
end
:hierarchy
begin
root lhipjoint rhipjoint lowerback
lhipjoint lfemur
lfemur ltibia
ltibia lfoot
lfoot ltoes
rhipjoint rfemur
rfemur rtibia
rtibia rfoot
rfoot rtoes
lowerback upperback
upperback thorax
thorax lowerneck lclavicle rclavicle
lowerneck upperneck
upperneck head
lclavicle lhumerus
lhumerus lradius
lradius lwrist
lwrist lhand lthumb
lhand lfingers
rclavicle rhumerus
rhumerus rradius
rradius rwrist
rwrist rhand rthumb
rhand rfingers
end

10
CGII/glsl/skinning.glfs Normal file
View file

@ -0,0 +1,10 @@
#version 330 compatibility
in vec3 color;
out vec4 result;
void main(void)
{
result = vec4(color, 1.0);
}

27
CGII/glsl/skinning.glgs Normal file
View file

@ -0,0 +1,27 @@
#version 330 compatibility
layout(triangles) in;
layout(triangle_strip, max_vertices = 3) out;
in vec4 position[];
out vec3 color;
uniform mat4 modelviewproj;
void main(void)
{
vec3 n = normalize(cross(position[1].xyz - position[0].xyz, position[2].xyz - position[0].xyz));
float c = 0.7 * abs(dot(n, normalize(vec3(1,1,1)))) + 0.15;
color = vec3(c, c, c);
gl_Position = modelviewproj * position[0];
EmitVertex();
gl_Position = modelviewproj * position[1];
EmitVertex();
gl_Position = modelviewproj * position[2];
EmitVertex();
EndPrimitive();
}

20
CGII/glsl/skinning.glvs Normal file
View file

@ -0,0 +1,20 @@
#version 330 compatibility
layout(location=0) in vec3 in_position;
layout(location=1) in vec4 bone_weights;
layout(location=2) in vec4 bone_indices;
out vec4 position;
uniform bool skinned;
uniform mat4 bone_matrices[50];
void main(void)
{
position = vec4(in_position, 1.0);
if(skinned)
{
/*Task: Implement Skinning */
}
}

81
CGII/src/Animation.cpp Normal file
View file

@ -0,0 +1,81 @@
// This source code is property of the Computer Graphics and Visualization
// chair of the TU Dresden. Do not distribute!
// Copyright (C) CGV TU Dresden - All Rights Reserved
//
#include "Animation.h"
#include <fstream>
bool Animation::read_amc_file(std::string filename, Skeleton* s)
{
frames.clear();
std::ifstream fin;
#ifdef _WIN32
std::wstring wfilename = cgv::utils::str2wstr(filename);
fin.open(wfilename);
#else
fin.open(filename);
#endif
if (!fin.good())
return false;
try{
while (!fin.eof())
{
char buf[CHARS_PER_LINE];
fin.getline(buf, CHARS_PER_LINE);
std::string str(buf);
str = trim(str); //remove whitespaces
if (str.empty())
continue;
if (str.find('#') == 0)
continue; //don't handle comments
if (str.find(':') == 0)
continue; //don't handle control sequences
if (std::isdigit(str[0]))
{
//new frame
frames.push_back(std::vector<AnimationFrameBone>());
continue;
}
//must be a bone line
std::stringstream ss(str);
std::string bone_name;
ss >> bone_name;
Bone* bone = s->find_bone(bone_name);
if (bone == nullptr)
return false;
std::vector<double> dof_values(bone->dof_count());
for (int i = 0; i < bone->dof_count(); ++i)
{
double value;
ss >> value;
dof_values[i] = value;
}
frames.back().push_back(AnimationFrameBone());
frames.back().back().bone = bone;
frames.back().back().dof_values.resize(bone->dof_count());
for (int i = 0; i < bone->dof_count(); ++i)
{
frames.back().back().dof_values[i] = dof_values[bone->get_dof(i)->get_index_in_amc()];
}
}
fin.close();
}
catch (...)
{
fin.close();
return false;
}
return true;
}
int Animation::frame_count() const { return frames.size(); }

24
CGII/src/Animation.h Normal file
View file

@ -0,0 +1,24 @@
// This source code is property of the Computer Graphics and Visualization
// chair of the TU Dresden. Do not distribute!
// Copyright (C) CGV TU Dresden - All Rights Reserved
//
#pragma once
#include "common.h"
#include "AnimationFrameBone.h"
#include "Skeleton.h"
#include <string>
class Animation
{
public:
bool read_amc_file(std::string filename, Skeleton*);
int frame_count() const;
private:
//Contains a std::vector<AnimationFrameBone> for each frame, which contains animation data for a set of bones.
std::vector<std::vector<AnimationFrameBone>> frames;
};

View file

@ -0,0 +1,19 @@
// This source code is property of the Computer Graphics and Visualization
// chair of the TU Dresden. Do not distribute!
// Copyright (C) CGV TU Dresden - All Rights Reserved
//
#pragma once
#include "Bone.h"
#include <vector>
//Represents animation data for a single bone
struct AnimationFrameBone
{
//The bone, for which animation data is specified
Bone* bone;
//Values for every bone dof in the same order as specified in the bone
std::vector<double> dof_values;
};

View file

@ -0,0 +1,67 @@
// This source code is property of the Computer Graphics and Visualization
// chair of the TU Dresden. Do not distribute!
// Copyright (C) CGV TU Dresden - All Rights Reserved
//
#include "AtomicTransform.h"
#include <cgv/math/transformations.h>
#include <libs/cgv_gl/gl/gl.h>
#include "math_helper.h"
void AtomicTransform::set_limits(double lower, double upper)
{
this->lower_limit = lower;
this->upper_limit = upper;
this->value = 0;
}
void AtomicTransform::set_value(const double& value, void*)
{
this->value = value;
changed_signal(value);
}
std::string AtomicTransform::get_name() const { return title; }
const double AtomicTransform::get_value(void*) const { return value; }
const double AtomicTransform::get_lower_limit() const { return lower_limit; }
const double AtomicTransform::get_upper_limit() const { return upper_limit; }
AtomicRotationTransform::AtomicRotationTransform(Vec3 axis)
: axis(axis)
{
lower_limit = -180;
upper_limit = 180;
value = 0;
}
Mat4 AtomicRotationTransform::calculate_matrix()
{
return rotate(axis, (float)value);
}
void AtomicRotationTransform::optimize_value(const Vec3& local_vector, const Vec3& target, bool inverse)
{
/*Task: Implement parameter optimization*/
}
AtomicTranslationTransform::AtomicTranslationTransform(int dim)
: dim(dim)
{
lower_limit = -10;
upper_limit = 10;
}
Mat4 AtomicTranslationTransform::calculate_matrix()
{
Mat4 result;
result.identity();
result(dim, 3) = (float)value;
return result;
}
void AtomicTranslationTransform::optimize_value(const Vec3& local_vector, const Vec3& target, bool inverse)
{
}

155
CGII/src/AtomicTransform.h Normal file
View file

@ -0,0 +1,155 @@
// This source code is property of the Computer Graphics and Visualization
// chair of the TU Dresden. Do not distribute!
// Copyright (C) CGV TU Dresden - All Rights Reserved
//
#pragma once
#include "common.h"
#include <memory>
#include <cgv/gui/control.h>
#include <cgv/signal/signal.h>
#include <cgv/math/inv.h>
#define PI 3.1415926f
class Transform
{
public:
//Calculates a matrix that represents the current transform.
virtual Mat4 calculate_matrix() = 0;
//Optimizes the current value, such that T * local_vector = target in a least-squares sense.
virtual void optimize_value(const Vec3& local_vector, const Vec3& target) = 0;
};
class StaticTransform : public Transform
{
public:
StaticTransform(const Mat4& t) : t(t) {}
Mat4 calculate_matrix() { return t; }
void optimize_value(const Vec3& local_vector, const Vec3& target) { }
private:
Mat4 t;
};
//Represents an arbitrary affine transform with exactly one scalar parameter
class AtomicTransform : public cgv::gui::control_provider<double>, public Transform
{
public:
//Sets the limits of the scalar parameter
void set_limits(double lower, double upper);
const double get_lower_limit() const;
const double get_upper_limit() const;
//Sets the current scalar parameter. Ignore ud.
virtual void set_value(const double& value, void* ud = nullptr);
//Gets the current scalar parameter. Ignore ud.
const double get_value(void* ud = nullptr) const;
//Calculates a matrix that represents the current transform.
virtual Mat4 calculate_matrix() = 0;
//Optimizes the current value, such that T * local_vector = target in a least-squares sense.
virtual void optimize_value(const Vec3& local_vector, const Vec3& target, bool inverse = false) = 0;
virtual void optimize_value(const Vec3& local_vector, const Vec3& target) { optimize_value(local_vector, target, false); }
std::string get_name() const;
//Signal that is raised whenever the scalar parameter changes
cgv::signal::signal<double> changed_signal;
//Sets the order in which the transform is specified in the animation file.
void set_index_in_amc(int i) { index_in_amc = i; }
//Get the order in which the transform is specified in the animation file.
int get_index_in_amc() const { return index_in_amc; }
protected:
double lower_limit, upper_limit;
double value;
std::string title;
int index_in_amc;
};
class AtomicRotationTransform : public AtomicTransform
{
public:
AtomicRotationTransform(Vec3 axis);
virtual Mat4 calculate_matrix();
virtual void optimize_value(const Vec3& local_vector, const Vec3& target, bool inverse = false);
protected:
Vec3 axis;
};
class AtomicXRotationTransform : public AtomicRotationTransform
{
public:
AtomicXRotationTransform() : AtomicRotationTransform(Vec3(1, 0, 0)) { title = "X-Rotation"; }
};
class AtomicYRotationTransform : public AtomicRotationTransform
{
public:
AtomicYRotationTransform() : AtomicRotationTransform(Vec3(0, 1, 0)) { title = "Y-Rotation"; }
};
class AtomicZRotationTransform : public AtomicRotationTransform
{
public:
AtomicZRotationTransform() : AtomicRotationTransform(Vec3(0, 0, 1)) { title = "Z-Rotation"; }
};
class AtomicTranslationTransform : public AtomicTransform
{
public:
AtomicTranslationTransform(int dim);
virtual Mat4 calculate_matrix();
virtual void optimize_value(const Vec3& local_vector, const Vec3& target, bool inverse = false);
private:
int dim;
};
class AtomicXTranslationTransform : public AtomicTranslationTransform
{
public:
AtomicXTranslationTransform() : AtomicTranslationTransform(0) { title = "X-Translation"; }
};
class AtomicYTranslationTransform : public AtomicTranslationTransform
{
public:
AtomicYTranslationTransform() : AtomicTranslationTransform(1) { title = "Y-Translation"; }
};
class AtomicZTranslationTransform : public AtomicTranslationTransform
{
public:
AtomicZTranslationTransform() : AtomicTranslationTransform(2) { title = "Z-Translation"; }
};
class InverseTransform : public Transform
{
public:
InverseTransform(std::shared_ptr<AtomicTransform> t) : t(t) { }
Mat4 calculate_matrix() { return cgv::math::inv(t->calculate_matrix()); }
void optimize_value(const Vec3& local_vector, const Vec3& target)
{
t->optimize_value(local_vector, target, true);
}
private:
std::shared_ptr<AtomicTransform> t;
};

106
CGII/src/Bone.cpp Normal file
View file

@ -0,0 +1,106 @@
// This source code is property of the Computer Graphics and Visualization
// chair of the TU Dresden. Do not distribute!
// Copyright (C) CGV TU Dresden - All Rights Reserved
//
#include "Bone.h"
#include <cgv/math/transformations.h>
#include <cgv/math/inv.h>
#include "math_helper.h"
Bone::Bone()
: parent(nullptr), length(0.0f), direction_in_world_space(0.0, 0.0, 0.0), translationTransforms(0)
{}
Bone::~Bone()
{
for (auto bone : children)
delete bone;
children.clear();
dofs.clear();
for (auto dof : orientation)
delete dof;
orientation.clear();
}
void Bone::calculate_matrices()
{
orientationTransformGlobalToLocal.identity();
std::for_each(orientation.begin(), orientation.end(), [&](AtomicTransform* t) {
orientationTransformGlobalToLocal = orientationTransformGlobalToLocal * t->calculate_matrix();
});
orientationTransformLocalToGlobal = cgv::math::inv(orientationTransformGlobalToLocal);
/*Task 2.1: Implement matrix calculation */
/*Task 4.6: Implement matrix calculation */
}
Mat4 Bone::calculate_transform_prev_to_current_with_dofs()
{
//Task 2.1: Implement matrix calculation
Mat4 t;
t.identity();
return t;
}
Mat4 Bone::calculate_transform_prev_to_current_without_dofs()
{
//Task 2.1: Implement matrix calculation
Mat4 t;
t.identity();
return t;
}
void Bone::add_dof(AtomicTransform* dof)
{
dof->set_index_in_amc(dofs.size());
if (dynamic_cast<AtomicTranslationTransform*>(dof))
{
dofs.push_front(std::shared_ptr<AtomicTransform>(dof));
++translationTransforms;
}
else
dofs.insert(dofs.begin() + translationTransforms, std::shared_ptr<AtomicTransform>(dof));
}
void Bone::set_name(const std::string& name) { this->name = name; }
const std::string& Bone::get_name() const { return name; }
void Bone::set_direction_in_world_space(const Vec3& direction) { this->direction_in_world_space = direction; }
const Vec3& Bone::get_direction_in_world_space() const { return direction_in_world_space; }
void Bone::set_length(float l) { this->length = l; }
float Bone::get_length() const { return length; }
void Bone::add_axis_rotation(AtomicTransform* transform) { orientation.push_front(transform); }
void Bone::add_child(Bone* child)
{
child->set_parent(this);
children.push_back(child);
}
Bone* Bone::child_at(int i) const { return children[i]; }
int Bone::childCount() const { return children.size(); }
void Bone::set_parent(Bone* parent)
{
this->parent = parent;
}
Bone* Bone::get_parent() const { return parent; }
int Bone::dof_count() const { return dofs.size(); }
std::shared_ptr<AtomicTransform> Bone::get_dof(int dofIndex) const { return dofs[dofIndex]; }
const Mat4& Bone::get_binding_pose_matrix() const
{
return transformLocalToGlobal;
}
const Mat4& Bone::get_translation_transform_current_joint_to_next() const { return translationTransformCurrentJointToNext; }
const Mat4& Bone::get_orientation_transform_prev_joint_to_current() const { return orientationTransformPrevJointToCurrent; }
Vec4 Bone::get_bone_local_root_position() const { return Vec4(0, 0, 0, 1); }
Vec4 Bone::get_bone_local_tip_position() const { return translationTransformCurrentJointToNext * Vec4(0, 0, 0, 1); }

124
CGII/src/Bone.h Normal file
View file

@ -0,0 +1,124 @@
// This source code is property of the Computer Graphics and Visualization
// chair of the TU Dresden. Do not distribute!
// Copyright (C) CGV TU Dresden - All Rights Reserved
//
#pragma once
#include "AtomicTransform.h"
#include <deque>
#include <memory>
// Represents a bone in a hierarchical skeleton
class Bone
{
public:
Bone();
~Bone();
//Adds a new degree of freedom to the bone. The bone maintains separate groups of
//translation transforms and other transforms. All translation transforms go first
//in the dof list, followed by all other transforms. Every new transform is added
//to the beginning of the respective group.
void add_dof(AtomicTransform* dof);
//Returns the number of degrees of freedom of this bone.
int dof_count() const;
//Returns the degree of freedom with the given index.
std::shared_ptr<AtomicTransform> get_dof(int dofIndex) const;
//Sets the identifying name of the bone
void set_name(const std::string& name);
//Returns the identifying name of the bone
const std::string& get_name() const;
//Sets a unit vector that describes the bone's direction in world coordinates
//(independent of the hierarchy)
void set_direction_in_world_space(const Vec3& direction);
//Returns a unit vector that describes the bone's direction in world coordinates
//(independent of the hierarchy)
const Vec3& get_direction_in_world_space() const;
//Sets the bone's geometric length
void set_length(float length);
//Returns the bone's geometric length
float get_length() const;
//Modifies the orientation of the bone's local coordinate system by setting
// O <= T * O,
//where O is the bone's local coordinate system transform and T is the new transform.
void add_axis_rotation(AtomicTransform* transform);
//Adds a new child to this bone and sets the parent of the child to the current bone.
void add_child(Bone* child);
//Returns the child with index i.
Bone* child_at(int i) const;
//Returns the number of children of this bone.
int childCount() const;
//Specifies the parent of this bone. The root bone has a null parent.
void set_parent(Bone* parent);
//Returns the parent of this bone. The root bone has a null parent.
Bone* get_parent() const;
//Calculates all relevant matrices from the given information in the ASF file.
void calculate_matrices();
//Calculates a matrix that transforms the parent's local coordinate system to the current bone's local coordinate system (model transform).
//It includes all dofs of the bone. Implemented in task 2.1
Mat4 calculate_transform_prev_to_current_with_dofs();
//Calculates a matrix that transforms the parent's local coordinate system to the current bone's local coordinate system (model transform).
//It does not include any of the bone's dofs. Implemented in task 2.1.
Mat4 calculate_transform_prev_to_current_without_dofs();
//Returns a matrix that represents a translation from the current bone to the next bone in the current bone's local coordinate system.
//Implemented in task 2.1.
const Mat4& get_translation_transform_current_joint_to_next() const;
//Returns a matrix that represents a rotation from the previous bone to the current bone in the previous bone's local coordinate system.
//Implemented in task 2.1.
const Mat4& get_orientation_transform_prev_joint_to_current() const;
//Returns the zero-vector (with w-component 1)
Vec4 get_bone_local_root_position() const;
//Returns the position of the bone's tip in the bone's coordinate system. Available after implementing task 2.1.
Vec4 get_bone_local_tip_position() const;
//Returns the system transform that transforms positions from the global coordinate system to the bone's local coordinate system.
//Available after implementing task 4.6.
const Mat4& get_binding_pose_matrix() const;
private:
//The following attributes are read from the ASF file
std::deque<std::shared_ptr<AtomicTransform>> dofs; //Degrees of freedom for the bone
std::string name; //The bone's name
Vec3 direction_in_world_space; //The bone's direction in world space (unit vector)
float length; //The bone's length
std::deque<AtomicTransform*> orientation; //The model transform from global space to bone space; multiply together from left to right
std::vector<Bone*> children; //child bones
Bone* parent; //parent bone
//Calculated attributes
//Transform directions are specified for model transforms (system transforms are in the opposite direction)
Mat4 orientationTransformPrevJointToCurrent; //Rotation matrix that transforms from the previous bone to the current bone (in the previous bone's coordinate system); Task 2.1
Mat4 translationTransformCurrentJointToNext; //Translation matrix that transforms from the current bone to the next bone (in the current bone's coordinate system); Task 2.1
Mat4 orientationTransformGlobalToLocal; //Rotation matrix that transforms from the global coordinate system to the current bone's local system. Available from the beginning.
Mat4 orientationTransformLocalToGlobal; //Rotation matrix that transforms from the current bone's local system to the global coordinate system. Available from the beginning.
//for skinning:
Mat4 translationTransformGlobalToLocal; //Translation matrix that transforms from the global coordinate system to the bone's local system. Task 4.6
Mat4 transformGlobalToLocal; //Combined rotation and translation that transforms from the global coordinate system to the bone's local system. Task 4.6
Mat4 transformLocalToGlobal;//Combined rotation and translation that transforms from the bone's local coordinate system to the global system. Task 4.6
int translationTransforms; //The number of translation transforms that have been added as dof
};

164
CGII/src/CGVDemo.cpp Normal file
View file

@ -0,0 +1,164 @@
// This source code is property of the Computer Graphics and Visualization
// chair of the TU Dresden. Do not distribute!
// Copyright (C) CGV TU Dresden - All Rights Reserved
//
#include "CGVDemo.h"
#include <cgv/utils/ostream_printf.h>
#include <cgv/gui/file_dialog.h>
#include <cgv/gui/dialog.h>
#include <cgv/render/view.h>
#include <cgv/base/find_action.h>
using namespace cgv::utils;
// The constructor of this class
CGVDemo::CGVDemo() : node("CGV Demo")
{
// Default setting for the render mode
show_coordinate_system = true;
slider_value = 0.0f;
// Connect the timer_event method to the (cgv-library) animation
// trigger to be called every 1/60 sec.
connect(get_animation_trigger().shoot, this, &CGVDemo::timer_event);
}
int local_test_value;
void local_test_value_changed(control<int>& c)
{
std::cout << "Local test value has been changed to " << local_test_value <<". "
<< "Old value was " << c.get_old_value() << std::endl;
}
// Create the gui elements
// This method overrides a virtual method of the provider base class.
void CGVDemo::create_gui() {
// Controls are chosen based on the variable's type
// Create a toggle button that controls the variable "show_coordinate_system".
// Every time this button is pressed, the method on_set is called
// that calls post_redraw to redraw the scene.
// Possible gui_types are "toggle" and "check"
add_member_control(this, "Show Coordinate System", show_coordinate_system, "toggle");
// Example control for a float or integer value
// Possible gui_types are "slider", "value_slider", "wheel", "dial", "adjuster", and "value_input"
add_member_control(this, "Demo Slider", slider_value, "value_slider", "min=0.0;max=5.0");
// This is how to set attributes programmatically
find_control(slider_value)->set("max", 7);
// add_member_control requires the variable's container to be a base_ptr. It
// then calls the container's on_set method when it changes the value. If a
// value that is not enclosed in a base_ptr should be targeted, add_control
// can be used and the signal can be connected manually:
auto slider = add_control("Non base_ptr", local_test_value, "value_slider", "min=0;max=20");
connect(slider->value_change, &local_test_value_changed);
// To add further control elements you can copy the lines above. Other control
// elements such as buttons exist. This line creates a button, which calls an
// arbitrary method. Whenever a click was performed, the method "button_pressed"
// is called. rebind() is used to target the member function.
connect_copy(add_button("Press me")->click,
rebind(this, &CGVDemo::button_pressed));
// Find the view
std::vector<cgv::render::view*> view_ptrs;
cgv::base::find_interface<cgv::render::view>(get_node(), view_ptrs);
if (view_ptrs.empty()) {
// If there is no view, we cannot update it
cgv::gui::message("could not find a view to adjust!!");
}
else
{
// Set view direction
view_ptrs[0]->set_view_dir(-1, -1, -1);
// Set focus point of view
double focus_point[3] = { 0, 0, 0 };
view_ptrs[0]->set_focus(focus_point);
// Set the scene's size at the focus point
view_ptrs[0]->set_y_extent_at_focus(1);
}
}
// The timer event. This method is called every 1/60 sec.
void CGVDemo::timer_event(double, double dt)
{
// Use post_redraw() to issue a new frame for animation
// dt it the time since the last call
}
// Method that is called whenever a gui element changes a bound value
void CGVDemo::on_set(void* member_ptr)
{
// Redraw the scene every time a gui value was changed
post_redraw();
}
// Demo button action
void CGVDemo::button_pressed()
{
std::cout << "I was pressed!" << std::endl;
//Sample file open dialog:
std::string filename = cgv::gui::file_open_dialog("Open", "Image Files (jpg,gif):*.jpg;*.gif|Video Files (avi):*.avi|All Files:*.*");
if (!filename.empty())
std::cout << filename << std::endl;
}
void CGVDemo::draw(context& c) {
// Disable face culling
glDisable(GL_CULL_FACE);
if (show_coordinate_system)
render_coordinate_system();
// Re-enable backface culling
glEnable(GL_CULL_FACE);
}
void CGVDemo::render_coordinate_system()
{
// Remember the OpenGL enable bits
glPushAttrib(GL_ENABLE_BIT);
// Disable lighting
glDisable(GL_LIGHTING);
// Start transferring line information
glBegin(GL_LINES);
// Show a red arrow towards the X axis
glColor3f(1.0f, 0.0f, 0.0f);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(0.5f, 0.0f, 0.0f);
// Show a green arrow towards the Y axis
glColor3f(0.0f, 1.0f, 0.0f);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(0.0f, 0.5f, 0.0f);
// Show a blue arrow towards the Z axis
glColor3f(0.0f, 0.0f, 1.0f);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(0.0f, 0.0f, 0.5f);
glEnd();
// Restore enable bits
glPopAttrib();
}

56
CGII/src/CGVDemo.h Normal file
View file

@ -0,0 +1,56 @@
// This source code is property of the Computer Graphics and Visualization
// chair of the TU Dresden. Do not distribute!
// Copyright (C) CGV TU Dresden - All Rights Reserved
//
#pragma once
#include "common.h"
#include <cgv/gui/trigger.h>
#include <cgv/gui/provider.h>
#include <cgv/render/drawable.h>
#include <cgv/render/context.h>
#include <cgv_gl/gl/gl.h>
using namespace cgv::base;
using namespace cgv::signal;
using namespace cgv::gui;
using namespace cgv::math;
using namespace cgv::render;
using namespace cgv::utils;
class CGVDemo :
public node, // obligatory base class
public drawable, // enables 3d view capabilities for this class
public provider // enables 2d gui capabilities for this class
{
private:
// True if coordinate systems shall be rendered
bool show_coordinate_system;
//Demo slider value
float slider_value;
// Render a simple coordinate system
void render_coordinate_system();
// The timer event. This method is called every 1/60 sec.
void timer_event(double, double dt);
// Demo button action for further buttons
void button_pressed();
// Method that is called whenever a gui element is clicked
void on_set(void* member_ptr);
public:
// The constructor of this class
CGVDemo();
// Create the gui elements
void create_gui();
// Draw the scene
void draw(context& c);
};

57
CGII/src/DataStore.cpp Normal file
View file

@ -0,0 +1,57 @@
// This source code is property of the Computer Graphics and Visualization
// chair of the TU Dresden. Do not distribute!
// Copyright (C) CGV TU Dresden - All Rights Reserved
//
#include "DataStore.h"
DataStore::DataStore()
: skeleton(nullptr), mesh(nullptr), endeffector(nullptr), base(nullptr), dof_changed_by_ik(false)
{ }
DataStore::~DataStore()
{
}
void DataStore::set_skeleton(std::shared_ptr<Skeleton> s)
{
skeleton = s;
skeleton_changed(skeleton);
}
std::shared_ptr<Skeleton> DataStore::get_skeleton() const
{
return skeleton;
}
void DataStore::set_mesh(std::shared_ptr<Mesh> m)
{
mesh = m;
mesh_changed(mesh);
}
std::shared_ptr<Mesh> DataStore::get_mesh() const
{
return mesh;
}
void DataStore::set_endeffector(Bone* b)
{
endeffector = b;
endeffector_changed(b);
}
Bone* DataStore::get_endeffector() const
{
return endeffector;
}
void DataStore::set_base(Bone* b)
{
base = b;
base_changed(b);
}
Bone* DataStore::get_base() const
{
return base;
}

56
CGII/src/DataStore.h Normal file
View file

@ -0,0 +1,56 @@
// This source code is property of the Computer Graphics and Visualization
// chair of the TU Dresden. Do not distribute!
// Copyright (C) CGV TU Dresden - All Rights Reserved
//
#pragma once
#include "Skeleton.h"
#include "Mesh.h"
#include "Animation.h"
#include <cgv/signal/signal.h>
#include <memory>
class DataStore
{
public:
// This signal is used to report a change of the skeleton to the viewer.
// Skeleton* is the only parameter of this signal. There are no signals
// with no parameters.
// Use connect(...) and connect_copy(...) to register a listener.
// Use operator() to call a signal.
cgv::signal::signal<std::shared_ptr<Skeleton>> skeleton_changed;
cgv::signal::signal<std::shared_ptr<Mesh>> mesh_changed;
cgv::signal::signal<Bone*> endeffector_changed;
cgv::signal::signal<Bone*> base_changed;
DataStore();
~DataStore();
//Used for Skeleton Visualization
void set_skeleton(std::shared_ptr<Skeleton>);
std::shared_ptr<Skeleton> get_skeleton() const;
//Used for Skinning
void set_mesh(std::shared_ptr<Mesh>);
std::shared_ptr<Mesh> get_mesh() const;
//Used for IK
void set_endeffector(Bone*);
Bone* get_endeffector() const;
void set_base(Bone*);
Bone* get_base() const;
//Specifies if the next dof change is caused by the Inverse Kinematics module
bool dof_changed_by_ik;
private:
std::shared_ptr<Skeleton> skeleton;
std::shared_ptr<Mesh> mesh;
Bone* endeffector, *base;
};

View file

@ -0,0 +1,48 @@
// This source code is property of the Computer Graphics and Visualization
// chair of the TU Dresden. Do not distribute!
// Copyright (C) CGV TU Dresden - All Rights Reserved
//
#include "IHasBoundingBox.h"
IHasBoundingBox::IHasBoundingBox(void)
{
reset_bounding_box();
}
void IHasBoundingBox::reset_bounding_box()
{
max = Vec3(-std::numeric_limits<float>::infinity());
min = Vec3(std::numeric_limits<float>::infinity());
}
IHasBoundingBox::~IHasBoundingBox(void)
{
}
Vec3 IHasBoundingBox::getMin()
{
return min;
}
Vec3 IHasBoundingBox::getMax()
{
return max;
}
void IHasBoundingBox::add_point(Vec3 p)
{
if (p.x() < min.x())
min.x() = p.x();
if (p.x() > max.x())
max.x() = p.x();
if (p.y() < min.y())
min.y() = p.y();
if (p.y()> max.y())
max.y() = p.y();
if (p.z() < min.z())
min.z() = p.z();
if (p.z() > max.z())
max.z() = p.z();
}

View file

@ -0,0 +1,33 @@
// This source code is property of the Computer Graphics and Visualization
// chair of the TU Dresden. Do not distribute!
// Copyright (C) CGV TU Dresden - All Rights Reserved
//
#pragma once
#include "common.h"
//Represents an object that contains a bounding box
class IHasBoundingBox
{
public:
IHasBoundingBox(void);
~IHasBoundingBox(void);
//Gets the bounding box' minimum corner coordinate.
Vec3 getMin();
//Gets the bounding box' maximum corner coordinate.
Vec3 getMax();
private:
Vec3 min, max;
protected:
//Adds a point to the bounding box. If the point lies outside of the bounding box,
//the bounding box is expanded accordingly.
void add_point(Vec3 position);
//
void reset_bounding_box();
};

176
CGII/src/IKViewer.cpp Normal file
View file

@ -0,0 +1,176 @@
// This source code is property of the Computer Graphics and Visualization
// chair of the TU Dresden. Do not distribute!
// Copyright (C) CGV TU Dresden - All Rights Reserved
//
#include "IKViewer.h"
#include "math_helper.h"
#include <unordered_set>
#include <cgv/gui/mouse_event.h>
#include <cgv/math/inv.h>
#include <cgv/math/mat.h>
IKViewer::IKViewer(DataStore* data)
: node("IK Viewer"), data(data), modifying(false), target_position(0, 0, 0, 1), max_iterations(20)
{
connect(data->endeffector_changed, this, &IKViewer::endeffector_changed);
connect(data->base_changed, this, &IKViewer::base_changed);
}
void IKViewer::endeffector_changed(Bone* b)
{
calculate_kinematic_chain(data->get_base(), data->get_endeffector());
post_redraw();
}
void IKViewer::base_changed(Bone* b)
{
calculate_kinematic_chain(data->get_base(), data->get_endeffector());
post_redraw();
}
void IKViewer::calculate_kinematic_chain(Bone* base, Bone* endeffector)
{
/*Task 3.1: Calculate kinematic chain*/
}
void IKViewer::optimize()
{
//used for correct GUI behavior
data->dof_changed_by_ik = true;
auto skeleton_size = (data->get_skeleton()->getMax() - data->get_skeleton()->getMin());
float distance_threshold = 0.0001f * std::max({ skeleton_size.x(), skeleton_size.y(), skeleton_size.z() });
//split the current matrix in:
// before_dof -> dof -> after_dof
/*Task 3.3: Implement CCD */
//used for correct GUI behavior
data->dof_changed_by_ik = false;
}
void IKViewer::set_target_position_2d(int x, int y)
{
auto ctx = get_context();
if (!ctx)
return;
//Get the model-view-projection matrix
GLfloat mv[16];
GLfloat proj[16];
glGetFloatv(GL_MODELVIEW_MATRIX, mv);
glGetFloatv(GL_PROJECTION_MATRIX, proj);
cgv::math::mat<float> modelview(4, 4, mv);
cgv::math::mat<float> projm(4, 4, proj);
cgv::math::mat<float> mvp = projm * modelview;
cgv::math::mat<float> inv_mvp = cgv::math::inv_44(mvp);
//Get the z-value of the current target
auto projected_target = mvp * cgv::math::vec<float>(4, &target_position[0]);
float z = projected_target.z() / projected_target.w();
//Unproject the screen position into the scene
int width = ctx->get_width();
int height = ctx->get_height();
float proj_position[4] = { (2.0f * x) / width - 1.0f, (-2.0f * y) / height + 1.0f, z, 1.0f };
auto unprojected = inv_mvp * cgv::math::vec<float>(4, proj_position);
unprojected *= 1.0f / unprojected.w();
target_position.x() = unprojected.x();
target_position.y() = unprojected.y();
target_position.z() = unprojected.z();
if (data->get_endeffector())
optimize();
post_redraw();
}
bool IKViewer::handle(event& e)
{
if (e.get_kind() == EID_MOUSE) {
cgv::gui::mouse_event me = (cgv::gui::mouse_event&) e;
switch (me.get_action()) {
case MA_PRESS:
if (me.get_button() == MB_LEFT_BUTTON && me.get_modifiers() == EM_CTRL) {
modifying = true;
set_target_position_2d(me.get_x(), me.get_y());
return true;
}
break;
case MA_RELEASE:
modifying = false;
break;
case MA_DRAG:
if (modifying)
{
set_target_position_2d(me.get_x(), me.get_y());
return true;
}
break;
default: break;
}
}
return false;
}
void IKViewer::stream_help(std::ostream& os)
{
}
void IKViewer::draw(cgv::render::context& ctx)
{
if (!data->get_skeleton())
return;
auto skeleton_size = (data->get_skeleton()->getMax() - data->get_skeleton()->getMin());
float scale = 0.2f * std::max({ skeleton_size.x(), skeleton_size.y(), skeleton_size.z() });
glBegin(GL_LINES);
if (data->get_endeffector())
{
glColor3f(1, 1, 1);
glVertex3f(target_position.x() - scale, target_position.y(), target_position.z());
glVertex3f(target_position.x() + scale, target_position.y(), target_position.z());
glVertex3f(target_position.x(), target_position.y() - scale, target_position.z());
glVertex3f(target_position.x(), target_position.y() + scale, target_position.z());
glVertex3f(target_position.x(), target_position.y(), target_position.z() - scale);
glVertex3f(target_position.x(), target_position.y(), target_position.z() + scale);
}
if (data->get_base())
{
glColor3f(0.5f, 1, 0.5f);
glVertex3f(current_base_matrix(0, 3) - scale, current_base_matrix(1, 3), current_base_matrix(2, 3));
glVertex3f(current_base_matrix(0, 3) + scale, current_base_matrix(1, 3), current_base_matrix(2, 3));
glVertex3f(current_base_matrix(0, 3), current_base_matrix(1, 3) - scale, current_base_matrix(2, 3));
glVertex3f(current_base_matrix(0, 3), current_base_matrix(1, 3) + scale, current_base_matrix(2, 3));
glVertex3f(current_base_matrix(0, 3), current_base_matrix(1, 3), current_base_matrix(2, 3) - scale);
glVertex3f(current_base_matrix(0, 3), current_base_matrix(1, 3), current_base_matrix(2, 3) + scale);
}
glEnd();
}
void IKViewer::create_gui()
{
add_member_control(this, "Max Iterations", max_iterations, "value_slider", "min=1;max=100");
}

64
CGII/src/IKViewer.h Normal file
View file

@ -0,0 +1,64 @@
// This source code is property of the Computer Graphics and Visualization
// chair of the TU Dresden. Do not distribute!
// Copyright (C) CGV TU Dresden - All Rights Reserved
//
#pragma once
#include "common.h"
#include "DataStore.h"
#include <list>
#include <cgv/gui/trigger.h>
#include <cgv/gui/provider.h>
#include <cgv/gui/event_handler.h>
#include <cgv/render/drawable.h>
#include <cgv/render/context.h>
#include <cgv_gl/gl/gl.h>
using namespace cgv::base;
using namespace cgv::signal;
using namespace cgv::gui;
using namespace cgv::math;
using namespace cgv::render;
using namespace cgv::utils;
class IKViewer : public node, public drawable, public provider, public event_handler
{
private:
DataStore* data;
void set_target_position_2d(int x, int y);
void endeffector_changed(Bone*);
void base_changed(Bone*);
void calculate_kinematic_chain(Bone* base, Bone* endeffector);
bool modifying; //Specifies if the user is currently modifying the IK target position
Vec4 target_position;
Mat4 current_endeffector_matrix; //transform from base to endeffector
Mat4 current_base_matrix; //transform from global origin to base
unsigned int max_iterations;
std::list<std::shared_ptr<Transform>> kinematic_chain;
void optimize();
public:
// The constructor of this class
IKViewer(DataStore*);
bool handle(cgv::gui::event& e);
void stream_help(std::ostream& os);
// Create the gui elements
void create_gui();
// Draw the scene
void draw(context& c);
};

213
CGII/src/Mesh.cpp Normal file
View file

@ -0,0 +1,213 @@
// This source code is property of the Computer Graphics and Visualization
// chair of the TU Dresden. Do not distribute!
// Copyright (C) CGV TU Dresden - All Rights Reserved
//
#include "Mesh.h"
#include <vector>
#include <fstream>
#include <sstream>
#include <queue>
bool Mesh::init_shaders(cgv::render::context& ctx)
{
cgv::render::shader_code vs, fs, gs;
if (!vs.read_and_compile(ctx, "glsl/skinning.glvs", cgv::render::ST_VERTEX)) {
std::cout << "error reading vertex shader\n" << vs.last_error.c_str() << std::endl;
return false;
}
if (!gs.read_and_compile(ctx, "glsl/skinning.glgs", cgv::render::ST_GEOMETRY)) {
std::cout << "error reading geometry shader\n" << gs.last_error.c_str() << std::endl;
return false;
}
if (!fs.read_and_compile(ctx, "glsl/skinning.glfs", cgv::render::ST_FRAGMENT)) {
std::cout << "error reading fragment shader\n" << vs.last_error.c_str() << std::endl;
return false;
}
if (!prog.create(ctx)) {
std::cout << "error creating program\n" << prog.last_error.c_str() << std::endl;
return false;
}
prog.attach_code(ctx, vs);
prog.attach_code(ctx, gs);
prog.attach_code(ctx, fs);
if (!prog.link(ctx)) {
std::cout << "link error\n" << prog.last_error.c_str() << std::endl;
return false;
}
return true;
}
Mesh::Mesh()
: has_attachment(false)
{
glGenBuffers(1, &indexBuffer);
glGenBuffers(1, &positionBuffer);
glGenBuffers(1, &boneIndexBuffer);
glGenBuffers(1, &boneWeightBuffer);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, boneWeightBuffer);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, boneIndexBuffer);
glVertexAttribPointer(2, 4, GL_INT, GL_FALSE, 0, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glEnableVertexAttribArray(0);
skinning_matrices = new GLfloat[50 * 16];
}
Mesh::~Mesh()
{
glDeleteBuffers(1, &indexBuffer);
glDeleteBuffers(1, &positionBuffer);
glDeleteBuffers(1, &boneIndexBuffer);
glDeleteBuffers(1, &boneWeightBuffer);
glDeleteVertexArrays(1, &vao);
delete[] skinning_matrices;
}
bool Mesh::read_obj(const char* filename)
{
std::ifstream f(filename);
std::string line;
cgv::math::fvec<float, 3> p;
unsigned int i, j, k;
positions.clear();
indices.clear();
reset_bounding_box();
int n_indices = 0;
while (std::getline(f, line))
{
if (line.length() == 0 || line[0] == '#')
continue;
else
{
std::stringstream ss(line);
ss.ignore(1);
if (line[0] == 'v')
{
ss >> p.x() >> p.y() >> p.z();
positions.push_back(p);
add_point(p);
}
else if (line[0] == 'f')
{
ss >> i;
ss.ignore(10, ' ');
ss >> j;
ss.ignore(10, ' ');
ss >> k;
indices.push_back(i - 1);
indices.push_back(j - 1);
indices.push_back(k - 1);
n_indices += 3;
}
}
}
f.close();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
glBufferData(GL_ARRAY_BUFFER, positions.size() * sizeof(cgv::math::fvec<float, 3>), &positions[0], GL_STATIC_DRAW);
return true;
}
void Mesh::read_attachment(std::string filename)
{
std::ifstream f(filename);
std::string line;
typedef cgv::math::fvec<int, 4> ivec4;
std::vector<ivec4> bone_indices;
std::vector<Vec4> bone_weights;
while (std::getline(f, line))
{
/*Task 4.5: Load attachment */
}
glBindBuffer(GL_ARRAY_BUFFER, boneIndexBuffer);
glBufferData(GL_ARRAY_BUFFER, bone_indices.size() * sizeof(ivec4), &bone_indices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, boneWeightBuffer);
glBufferData(GL_ARRAY_BUFFER, bone_weights.size() * sizeof(Vec4), &bone_weights[0], GL_STATIC_DRAW);
f.close();
has_attachment = true;
}
void Mesh::set_skinning_matrices(const std::vector<Mat4>& matrices)
{
for (size_t i = 0; i < matrices.size(); ++i)
{
for (int j = 0; j < 16; ++j)
skinning_matrices[16 * i + j] = matrices[i][j];
}
n_bones = matrices.size();
}
void Mesh::draw(cgv::render::context& ctx)
{
GLfloat mv[16];
GLfloat proj[16];
glGetFloatv(GL_MODELVIEW_MATRIX, mv);
glGetFloatv(GL_PROJECTION_MATRIX, proj);
Mat4 modelview(mv);
Mat4 projm(proj);
Mat4 mvp = projm * modelview;
prog.set_uniform(ctx, "modelviewproj", mvp);
prog.set_uniform(ctx, "skinned", has_attachment);
prog.enable(ctx);
glBindVertexArray(vao);
if (has_attachment)
{
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
GLint program;
glGetIntegerv(GL_CURRENT_PROGRAM, &program);
GLint matrices_location = glGetUniformLocation(program, "bone_matrices");
glUniformMatrix4fv(matrices_location, n_bones, GL_FALSE, skinning_matrices);
}
else
{
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
}
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
prog.disable(ctx);
}

54
CGII/src/Mesh.h Normal file
View file

@ -0,0 +1,54 @@
// This source code is property of the Computer Graphics and Visualization
// chair of the TU Dresden. Do not distribute!
// Copyright (C) CGV TU Dresden - All Rights Reserved
//
#pragma once
#include "common.h"
#include "IHasBoundingBox.h"
#include <libs/cgv_gl/gl/gl.h>
#include <cgv/render/shader_code.h>
#include <cgv/render/shader_program.h>
#include <string>
class Mesh : public IHasBoundingBox
{
public:
Mesh();
~Mesh();
//Compiles all used shaders.
static bool init_shaders(cgv::render::context& ctx);
//Loads geometry data from an OBJ file.
bool read_obj(const char* filename);
//Loads attachment data from a Pinocchio file.
void read_attachment(std::string filename);
//Draws the mesh
void draw(cgv::render::context& ctx);
//Sets the matrices used for skinning.
void set_skinning_matrices(const std::vector<Mat4>& matrices);
private:
static cgv::render::shader_program prog;
std::vector<cgv::math::fvec<float, 3>> positions;
std::vector<unsigned int> indices;
GLuint indexBuffer;
GLuint positionBuffer;
GLuint boneIndexBuffer;
GLuint boneWeightBuffer;
GLuint vao;
GLfloat* skinning_matrices;
int n_bones;
bool has_attachment;
};

313
CGII/src/Skeleton.cpp Normal file
View file

@ -0,0 +1,313 @@
// This source code is property of the Computer Graphics and Visualization
// chair of the TU Dresden. Do not distribute!
// Copyright (C) CGV TU Dresden - All Rights Reserved
//
#include "Skeleton.h"
#include <fstream>
#include <map>
#include <string>
#include <sstream>
#include "math_helper.h"
Skeleton::Skeleton()
{
origin.identity();
}
Skeleton::~Skeleton()
{
if (root)
delete root;
}
Bone* Skeleton::get_root() const { return root; }
const Mat4& Skeleton::get_origin() const { return origin; }
Vec3 Skeleton::get_origin_vec() const { return Vec3(origin(0, 3), origin(1, 3), origin(2,3)); }
void Skeleton::set_origin(const Vec3& v) { origin = translate(v); }
void Skeleton::set_origin(const Mat4& m) { origin = m; }
enum ParseState
{
Ignore,
Root,
BoneData,
Hierarchy,
};
bool Skeleton::fromASFFile(const std::string& filename)
{
origin.identity();
std::ifstream fin;
reset_bounding_box();
ParseState state = Ignore;
Bone* current_node = nullptr;
bones.clear();
int n_dofs;
try
{
#ifdef _WIN32
std::wstring wfilename = cgv::utils::str2wstr(filename);
fin.open(wfilename);
#else
fin.open(filename);
#endif
if (!fin.good())
return false;
while (!fin.eof())
{
char buf[CHARS_PER_LINE];
fin.getline(buf, CHARS_PER_LINE);
std::string str(buf);
str = trim(str); //remove whitespaces
if (str.find('#') == 0)
continue; //don't handle comments
if (str.find(':') == 0)
{
if (str.find(":version") == 0)
version = str.substr(9);
else if (str.find(":name") == 0)
name = str.substr(6);
else if (str.find(":root") == 0)
{
state = Root;
current_node = new Bone();
current_node->set_name("root");
bones["root"] = current_node;
}
else if (str.find(":bonedata") == 0)
state = BoneData;
else if (str.find(":hierarchy") == 0)
state = Hierarchy;
else state = Ignore;
continue;
}
switch (state)
{
case Ignore:
//ignore this line
break;
case Root:
if (str.find("order") == 0)
{
std::string dofs = str.substr(6);
std::string dofstr;
std::stringstream ss(dofs);
n_dofs = 0;
while (!ss.eof())
{
ss >> dofstr;
AtomicTransform* dof;
if (dofstr.find("RX") == 0)
dof = new AtomicXRotationTransform();
else if (dofstr.find("RY") == 0)
dof = new AtomicYRotationTransform();
else if (dofstr.find("RZ") == 0)
dof = new AtomicZRotationTransform();
else if (dofstr.find("TX") == 0)
dof = new AtomicXTranslationTransform();
else if (dofstr.find("TY") == 0)
dof = new AtomicYTranslationTransform();
else if (dofstr.find("TZ") == 0)
dof = new AtomicZTranslationTransform();
dof->set_value(0);
current_node->add_dof(dof);
++n_dofs;
}
}
break;
case BoneData:
if (str.find("begin") == 0)
current_node = new Bone();
else if (str.find("name") == 0)
{
std::string name = str.substr(5);
current_node->set_name(name);
bones[name] = current_node;
}
else if (str.find("direction") == 0)
{
std::string direction = str.substr(10);
float dx, dy, dz;
std::stringstream ss(direction);
ss >> dx >> dy >> dz;
current_node->set_direction_in_world_space(Vec3(dx, dy, dz));
}
else if (str.find("length") == 0)
{
std::string length = str.substr(7);
float l;
std::stringstream ss(length);
ss >> l;
current_node->set_length(l);
}
else if (str.find("axis") == 0)
{
std::string axis = str.substr(5);
float a[3];
std::string order;
std::stringstream ss(axis);
ss >> a[0] >> a[1] >> a[2] >> order;
for (int i = 0; i < 3; ++i)
{
AtomicTransform* t;
if (order.at(i) == 'X')
t = new AtomicXRotationTransform();
else if (order.at(i) == 'Y')
t = new AtomicYRotationTransform();
else if (order.at(i) == 'Z')
t = new AtomicZRotationTransform();
t->set_value(a[i]);
current_node->add_axis_rotation(t);
}
}
else if (str.find("dof") == 0)
{
std::string dofs = str.substr(4);
std::string dofstr;
std::stringstream ss(dofs);
n_dofs = 0;
while (!ss.eof())
{
ss >> dofstr;
AtomicTransform* dof;
if (dofstr.find("rx") == 0)
dof = new AtomicXRotationTransform();
else if (dofstr.find("ry") == 0)
dof = new AtomicYRotationTransform();
else if (dofstr.find("rz") == 0)
dof = new AtomicZRotationTransform();
current_node->add_dof(dof);
++n_dofs;
}
}
else if (str.find("limits") == 0)
{
std::string limits = str.substr(7);
for (int i = 0; i < n_dofs; ++i)
{
if (i > 0)
{
fin.getline(buf, CHARS_PER_LINE);
limits = std::string(buf);
limits = trim(limits);
}
limits = limits.substr(limits.find('(') + 1);
std::stringstream ss(limits);
float lower, upper;
ss >> lower >> upper;
current_node->get_dof(n_dofs - i - 1)->set_limits(lower, upper);
}
}
break;
case Hierarchy:
if (str.find("begin") == std::string::npos && str.find("end") == std::string::npos)
{
std::stringstream ss(str);
std::string parentstr;
ss >> parentstr;
Bone* parent = bones[parentstr];
std::string childstr;
while (!ss.eof())
{
ss >> childstr;
Bone* child = bones[childstr];
parent->add_child(child);
}
}
}
}
fin.close();
root = bones["root"];
//root->revert_dofs();
postprocess(root, Vec3(0, 0, 0));
return true;
}
catch (...)
{
fin.close();
return false;
}
}
void Skeleton::postprocess(Bone* node, const Vec3& global_position)
{
//For display adaptation
auto bone_offset_in_global_system = node->get_direction_in_world_space() * node->get_length();
auto bone_tip_in_global_system = global_position + bone_offset_in_global_system;
add_point(bone_tip_in_global_system);
node->calculate_matrices();
int n = node->childCount();
for (int i = 0; i < n; ++i)
{
postprocess(node->child_at(i), bone_tip_in_global_system);
}
}
void Skeleton::write_pinocchio_file(const std::string& filename)
{
std::ofstream o;
#ifdef _WIN32
std::wstring wfilename = cgv::utils::str2wstr(filename);
o.open(wfilename, std::ios::out);
#else
o.open(filename, std::ios::out);
#endif
if (o)
{
/*Task 4.1: Write Pinocchio file into o */
}
o.close();
}
void Skeleton::read_pinocchio_file(std::string filename)
{
std::ifstream o;
#ifdef _WIN32
std::wstring wfilename = cgv::utils::str2wstr(filename);
o.open(wfilename, std::ios::in);
#else
o.open(filename, std::ios::in);
#endif
if (o)
{
/*Task 4.1: Read Pinocchio file */
}
o.close();
postprocess(root, get_origin_vec());
}
void Skeleton::get_skinning_matrices(std::vector<Mat4>& matrices)
{
/*Task 4.6: Calculate skinning matrices */
}
Bone* Skeleton::find_bone(const std::string& name) const
{
auto it = bones.find(name);
if (it == bones.end())
return nullptr;
else
return it->second;
}

54
CGII/src/Skeleton.h Normal file
View file

@ -0,0 +1,54 @@
// This source code is property of the Computer Graphics and Visualization
// chair of the TU Dresden. Do not distribute!
// Copyright (C) CGV TU Dresden - All Rights Reserved
//
#pragma once
#include "Bone.h"
#include "common.h"
#include "IHasBoundingBox.h"
#include <vector>
class Skeleton : public IHasBoundingBox
{
public:
Skeleton();
~Skeleton();
//Loads skeleton data from an ASF file.
bool fromASFFile(const std::string& filename);
//Writes the current skeleton to a Pinocchio file.
void write_pinocchio_file(const std::string& filename);
//Loads a Pinocchio skeleton file and adapts the current skeleton according to this file.
void read_pinocchio_file(std::string filename);
//Fille the matrices vector with the skinning matrices for all bones in DFS order
void get_skinning_matrices(std::vector<Mat4>& matrices);
//Returns the skeleton's root bone
Bone* get_root() const;
const Mat4& get_origin() const;
Vec3 get_origin_vec() const;
void set_origin(const Vec3&);
void set_origin(const Mat4&);
Bone* find_bone(const std::string& name) const;
private:
Mat4 origin;
std::string version;
std::string name;
Bone* root;
void postprocess(Bone* node, const Vec3& global_position);
std::map<const std::string, Bone*> bones;
};

282
CGII/src/SkeletonViewer.cpp Normal file
View file

@ -0,0 +1,282 @@
// This source code is property of the Computer Graphics and Visualization
// chair of the TU Dresden. Do not distribute!
// Copyright (C) CGV TU Dresden - All Rights Reserved
//
#include "SkeletonViewer.h"
#include <cgv/utils/ostream_printf.h>
#include <cgv/gui/file_dialog.h>
#include <cgv/gui/dialog.h>
#include <cgv/gui/key_event.h>
#include <cgv/render/view.h>
#include <cgv/base/find_action.h>
#include "math_helper.h"
using namespace cgv::utils;
cgv::render::shader_program Mesh::prog;
// The constructor of this class
SkeletonViewer::SkeletonViewer(DataStore* data)
: node("Skeleton Viewer"), data(data)
{
connect(data->skeleton_changed, this, &SkeletonViewer::skeleton_changed);
connect(get_animation_trigger().shoot, this, &SkeletonViewer::timer_event);
}
//draws a part of a skeleton, represented by the given root node
void SkeletonViewer::draw_skeleton_subtree(Bone* node, const Mat4& global_to_parent_local)
{
//Task: Draw skeleton
}
void SkeletonViewer::timer_event(double, double dt)
{
/*Task: Implement animation */
}
void SkeletonViewer::start_animation()
{
//Task: Implement animation
}
void SkeletonViewer::stop_animation()
{
//Task: Implement animation
}
void SkeletonViewer::skeleton_changed(std::shared_ptr<Skeleton> s)
{
// This function is called whenever the according signal of the
// data store has been called.
//Rebuild the tree-view
generate_tree_view_nodes();
//Fit view to skeleton
std::vector<cgv::render::view*> view_ptrs;
cgv::base::find_interface<cgv::render::view>(get_node(), view_ptrs);
if (view_ptrs.empty()) {
// If there is no view, we cannot update it
cgv::gui::message("could not find a view to adjust!!");
}
else
{
Vec3 center = (s->getMin() + s->getMax()) * 0.5;
view_ptrs[0]->set_focus(center.x(), center.y(), center.z());
// Set the scene's size at the focus point
view_ptrs[0]->set_y_extent_at_focus(s->getMax().y() - s->getMin().y());
}
//connect signals
recursive_connect_signals(s->get_root());
post_redraw();
}
void SkeletonViewer::recursive_connect_signals(Bone* b)
{
for (int i = 0; i < b->dof_count(); ++i)
connect(b->get_dof(i)->changed_signal, this, &SkeletonViewer::dof_changed);
for (int i = 0; i < b->childCount(); ++i)
recursive_connect_signals(b->child_at(i));
}
void SkeletonViewer::dof_changed(double)
{
if (!data->dof_changed_by_ik)
data->set_endeffector(nullptr);
post_redraw();
}
void SkeletonViewer::generate_tree_view_nodes()
{
tree_view->remove_all_children();
gui_to_bone.clear();
if (!data->get_skeleton() || !data->get_skeleton()->get_root())
return;
generate_tree_view_nodes(tree_view, data->get_skeleton()->get_root());
}
void SkeletonViewer::generate_tree_view_nodes(gui_group_ptr parent, Bone* bone)
{
if (bone->childCount() == 0)
{
//If this is a leaf, use a button
auto button = parent->add_button(bone->get_name(), "", "");
gui_to_bone[button] = bone;
}
else
{
//If this is not a leaf, use a group
auto g = parent->add_group(bone->get_name(), "", "", "");
gui_to_bone[g] = bone;
for (int i = 0; i < bone->childCount(); ++i)
generate_tree_view_nodes(g, bone->child_at(i));
}
}
void SkeletonViewer::start_choose_base()
{
Bone* b = data->get_endeffector();
data->set_endeffector(nullptr);
data->set_base(b);
}
void SkeletonViewer::tree_selection_changed(base_ptr p, bool select)
{
bone_group->remove_all_children();
if (select)
{
Bone* bone = gui_to_bone.at(p);
generate_bone_gui(bone);
data->set_endeffector(bone);
}
else
{
data->set_endeffector(nullptr);
}
}
std::string SkeletonViewer::get_parent_type() const
{
return "layout_group";
}
void SkeletonViewer::load_skeleton()
{
std::string filename = cgv::gui::file_open_dialog("Open", "Skeleton Files (*.asf):*.asf");
if (!filename.empty())
{
auto s = std::make_shared<Skeleton>();
if (s->fromASFFile(filename))
{
data->set_skeleton(s);
data->set_endeffector(nullptr);
data->set_base(s->get_root());
}
else
{
cgv::gui::message("Could not load specified ASF file.");
}
}
}
void SkeletonViewer::write_pinocchio()
{
if (!data->get_skeleton())
{
cgv::gui::message("An ASF skeleton has to be loaded first.");
return;
}
std::string filename = cgv::gui::file_save_dialog("Save", "Pinocchio Skeleton (*.txt):*.txt");
if (!filename.empty())
{
data->get_skeleton()->write_pinocchio_file(filename);
}
}
void SkeletonViewer::load_pinocchio()
{
if (!data->get_skeleton())
{
cgv::gui::message("An ASF skeleton has to be loaded first.");
return;
}
std::string filename = cgv::gui::file_open_dialog("Open", "Pinocchio skeleton (*.out):*.out");
if (!filename.empty())
{
data->get_skeleton()->read_pinocchio_file(filename);
skeleton_changed(data->get_skeleton());
}
}
void SkeletonViewer::load_animation()
{
if (!data->get_skeleton())
{
cgv::gui::message("An ASF skeleton has to be loaded first.");
return;
}
std::string filename = cgv::gui::file_open_dialog("Open", "Animation File (*.amc):*.amc");
if (!filename.empty())
{
/*Task: Load animation */
}
}
// Create the gui elements
void SkeletonViewer::create_gui()
{
//Bone tree view
parent_group->multi_set("layout='table';rows=3;spacings='normal';");
tree_view = add_group("", "tree_group", "h=300;column_heading_0='Bones';column_width_0=-1", "f");
bone_group = add_group("", "align_group", "h=150", "f");
auto dock_group = add_group("", "dockable_group", "", "fF");
connect(tree_view->on_selection_change, this, &SkeletonViewer::tree_selection_changed);
generate_tree_view_nodes();
//Other GUI elements
auto gui_group = dock_group->add_group("", "align_group", "", "f");
connect_copy(gui_group->add_button("Load ASF skeleton", "", "\n")->click,
rebind(this, &SkeletonViewer::load_skeleton));
connect_copy(gui_group->add_button("Load Animation", "", "\n")->click,
rebind(this, &SkeletonViewer::load_animation));
connect_copy(gui_group->add_button("Start Animation", "", "\n")->click,
rebind(this, &SkeletonViewer::start_animation));
connect_copy(gui_group->add_button("Stop Animation", "", "\n")->click,
rebind(this, &SkeletonViewer::stop_animation));
connect_copy(gui_group->add_button("Choose IK Base", "", "\n")->click,
rebind(this, &SkeletonViewer::start_choose_base));
connect_copy(gui_group->add_button("Write Pinocchio skeleton", "", "\n")->click,
rebind(this, &SkeletonViewer::write_pinocchio));
connect_copy(gui_group->add_button("Load Pinocchio skeleton", "", "\n")->click,
rebind(this, &SkeletonViewer::load_pinocchio));
}
void SkeletonViewer::generate_bone_gui(Bone* bone)
{
// Add bone-specific gui elements to bone_group.
// Use the layout "\n" to specify vertical alignment
bone_group->add_view("Selected Bone", bone->get_name());
for (int i = 0; i < bone->dof_count(); ++i)
{
auto dof = bone->get_dof(i);
auto slider = bone_group->add_control<double>(dof->get_name(), dof.get(), "value_slider");
slider->set("min", dof->get_lower_limit());
slider->set("max", dof->get_upper_limit());
}
}
void SkeletonViewer::draw(context& c)
{
glDisable(GL_LIGHTING);
glDisable(GL_CULL_FACE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
if (data->get_skeleton() != nullptr)
draw_skeleton_subtree(data->get_skeleton()->get_root(), data->get_skeleton()->get_origin());
}

71
CGII/src/SkeletonViewer.h Normal file
View file

@ -0,0 +1,71 @@
// This source code is property of the Computer Graphics and Visualization
// chair of the TU Dresden. Do not distribute!
// Copyright (C) CGV TU Dresden - All Rights Reserved
//
#pragma once
#include "common.h"
#include "DataStore.h"
#include <cgv/gui/trigger.h>
#include <cgv/gui/provider.h>
#include <cgv/gui/event_handler.h>
#include <cgv/render/drawable.h>
#include <cgv/render/context.h>
#include <cgv_gl/gl/gl.h>
using namespace cgv::base;
using namespace cgv::signal;
using namespace cgv::gui;
using namespace cgv::math;
using namespace cgv::render;
using namespace cgv::utils;
class SkeletonViewer : public node, public drawable, public provider
{
private:
DataStore* data;
gui_group_ptr tree_view;
gui_group_ptr bone_group;
// Maps gui elements in the tree view to a specific bone
std::map<base_ptr, Bone*> gui_to_bone;
// slot for the signal
void timer_event(double, double dt);
void skeleton_changed(std::shared_ptr<Skeleton>);
void generate_tree_view_nodes();
void generate_tree_view_nodes(gui_group_ptr parent, Bone* bone);
void tree_selection_changed(base_ptr p, bool select);
void generate_bone_gui(Bone* bone);
void load_skeleton();
void write_pinocchio();
void load_pinocchio();
void load_animation();
void start_choose_base();
void draw_skeleton_subtree(Bone* node, const Mat4& global_to_parent_local);
void dof_changed(double new_value);
void recursive_connect_signals(Bone* b);
void start_animation();
void stop_animation();
public:
// The constructor of this class
SkeletonViewer(DataStore*);
// Create the gui elements
void create_gui();
// Draw the scene
void draw(context& c);
std::string get_parent_type() const;
};

View file

@ -0,0 +1,103 @@
// This source code is property of the Computer Graphics and Visualization
// chair of the TU Dresden. Do not distribute!
// Copyright (C) CGV TU Dresden - All Rights Reserved
//
#include "SkinnedMeshViewer.h"
#include <cgv/gui/file_dialog.h>
#include <cgv/gui/dialog.h>
#include <cgv/render/view.h>
#include <cgv/base/find_action.h>
SkinnedMeshViewer::SkinnedMeshViewer(DataStore* data)
: node("Mesh Viewer"), data(data)
{
connect(data->mesh_changed, this, &SkinnedMeshViewer::mesh_changed);
}
bool SkinnedMeshViewer::init(context& ctx)
{
cgv::render::gl::ensure_glew_initialized();
if(!Mesh::init_shaders(ctx))
cgv::gui::message("Could not init shaders.");
return true;
}
void SkinnedMeshViewer::mesh_changed(std::shared_ptr<Mesh> m)
{
//Fit view to skeleton
std::vector<cgv::render::view*> view_ptrs;
cgv::base::find_interface<cgv::render::view>(get_node(), view_ptrs);
if (view_ptrs.empty()) {
// If there is no view, we cannot update it
cgv::gui::message("could not find a view to adjust!!");
}
else
{
Vec3 center = (m->getMin() + m->getMax()) * 0.5;
view_ptrs[0]->set_focus(center.x(), center.y(), center.z());
// Set the scene's size at the focus point
view_ptrs[0]->set_y_extent_at_focus(m->getMax().y() - m->getMin().y());
}
post_redraw();
}
void SkinnedMeshViewer::create_gui()
{
connect_copy(add_button("Load OBJ mesh", "", "\n")->click,
rebind(this, &SkinnedMeshViewer::load_mesh));
connect_copy(add_button("Load Pinocchio attachment", "", "\n")->click,
rebind(this, &SkinnedMeshViewer::load_attachment));
}
void SkinnedMeshViewer::load_mesh()
{
std::string filename = cgv::gui::file_open_dialog("Open", "OBJ Files (*.obj):*.obj");
if (!filename.empty())
{
auto m = std::make_shared<Mesh>();
if (m->read_obj(filename.c_str()))
data->set_mesh(m);
else
{
cgv::gui::message("Could not load specified OBJ file.");
}
}
}
void SkinnedMeshViewer::load_attachment()
{
if (!data->get_mesh())
{
cgv::gui::message("A mesh has to be loaded first.");
return;
}
std::string filename = cgv::gui::file_open_dialog("Open", "Pinocchio attachment (*.out):*.out");
if (!filename.empty())
{
data->get_mesh()->read_attachment(filename);
post_redraw();
}
}
void SkinnedMeshViewer::draw(context& c)
{
glEnable(GL_CULL_FACE);
glDisable(GL_BLEND);
if (data->get_mesh())
{
if (data->get_skeleton())
{
std::vector<Mat4> skinning_matrices;
data->get_skeleton()->get_skinning_matrices(skinning_matrices);
data->get_mesh()->set_skinning_matrices(skinning_matrices);
}
data->get_mesh()->draw(c);
}
}

View file

@ -0,0 +1,48 @@
//
// This source code is property of the Computer Graphics and Visualization
// chair of the TU Dresden. Do not distribute!
// Copyright (C) 2016 CGV TU Dresden - All Rights Reserved
//
#pragma once
#include "common.h"
#include "DataStore.h"
#include "Mesh.h"
#include <cgv/gui/trigger.h>
#include <cgv/gui/provider.h>
#include <cgv/render/drawable.h>
#include <cgv/render/context.h>
#include <cgv_gl/gl/gl.h>
using namespace cgv::base;
using namespace cgv::signal;
using namespace cgv::gui;
using namespace cgv::math;
using namespace cgv::render;
using namespace cgv::utils;
class SkinnedMeshViewer : public node, public drawable, public provider
{
private:
DataStore* data;
protected:
virtual bool init(context&);
void mesh_changed(std::shared_ptr<Mesh>);
void load_mesh();
void load_attachment();
public:
// The constructor of this class
SkinnedMeshViewer(DataStore*);
// Create the gui elements
void create_gui();
// Draw the scene
void draw(context& c);
};

35
CGII/src/common.h Normal file
View file

@ -0,0 +1,35 @@
// This source code is property of the Computer Graphics and Visualization
// chair of the TU Dresden. Do not distribute!
// Copyright (C) CGV TU Dresden - All Rights Reserved
//
#pragma once
#include <cgv/math/fvec.h>
#include <cgv/math/fmat.h>
#include <cctype>
typedef cgv::math::fvec<float, 3> Vec3;
typedef cgv::math::fvec<float, 4> Vec4;
typedef cgv::math::fmat<float, 4, 4> Mat4;
const int CHARS_PER_LINE = 512;
//source of trim functions: http://stackoverflow.com/questions/216823/whats-the-best-way-to-trim-stdstring
// trim from start
static inline std::string &ltrim(std::string &s) {
s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
return s;
}
// trim from end
static inline std::string &rtrim(std::string &s) {
s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
return s;
}
// trim from both ends
static inline std::string &trim(std::string &s) {
return ltrim(rtrim(s));
}

39
CGII/src/main.cpp Normal file
View file

@ -0,0 +1,39 @@
// This source code is property of the Computer Graphics and Visualization
// chair of the TU Dresden. Do not distribute!
// Copyright (C) CGV TU Dresden - All Rights Reserved
//
// The main file of the plugin. It defines a global register variable
// "global_initializer" that is initialized when the plugin is loaded.
#include <cgv/base/register.h>
#include "CGVDemo.h"
#include "DataStore.h"
#include "SkeletonViewer.h"
#include "SkinnedMeshViewer.h"
#include "IKViewer.h"
using namespace cgv::base;
struct Initializer
{
DataStore* data;
Initializer()
{
register_object(base_ptr(new CGVDemo()), "");
data = new DataStore();
/*register_object(base_ptr(new SkeletonViewer(data)), "");*/
/*register_object(base_ptr(new IKViewer(data)), "");*/
/*register_object(base_ptr(new SkinnedMeshViewer(data)), "");*/
}
~Initializer()
{
delete data;
}
} global_initializer;

56
CGII/src/math_helper.h Normal file
View file

@ -0,0 +1,56 @@
// This source code is property of the Computer Graphics and Visualization
// chair of the TU Dresden. Do not distribute!
// Copyright (C) CGV TU Dresden - All Rights Reserved
//
#pragma once
#include "common.h"
#include <cgv/math/transformations.h>
///creates a 4x4 rotation matrix
template <typename T>
const cgv::math::fmat<T, 4, 4> rotate(const cgv::math::fvec<T, 3> axis, T angle_degrees)
{
auto matrix = cgv::math::rotate_44(axis.x(), axis.y(), axis.z(), angle_degrees);
Mat4 result;
for (int i = 0; i < 4; ++i)
for (int j = 0; j < 4; ++j)
result(i, j) = matrix(i, j);
return result;
}
///creates a 4x4 translation matrix
template <typename T>
const cgv::math::fmat<T, 4, 4> translate(const T&x, const T &y, const T&z)
{
cgv::math::fmat<T, 4, 4> m;
m.identity();
m(0, 3) = x;
m(1, 3) = y;
m(2, 3) = z;
return m;
}
///creates a 4x4 translation matrix
template <typename T>
const cgv::math::fmat<T, 4, 4> translate(const cgv::math::fvec<T, 3> v)
{
cgv::math::fmat<T, 4, 4> m;
m.identity();
m(0, 3) = v.x();
m(1, 3) = v.y();
m(2, 3) = v.z();
return m;
}
///creates a 4x4 translation matrix
template <typename T>
const cgv::math::fmat<T, 4, 4> translate(const cgv::math::fvec<T, 4> v)
{
cgv::math::fmat<T, 4, 4> m;
m.identity();
m(0, 3) = v.x();
m(1, 3) = v.y();
m(2, 3) = v.z();
return m;
}

48
framework/buildLinux.sh Normal file
View file

@ -0,0 +1,48 @@
#!/bin/sh
echo "Ich versuche nun das Framework herunterzuladen, zu kompilieren und in dem entsprechenden Framework-Ordner zu installieren."
echo "Die Installation erfolgt nur lokal in ../framework."
echo "Die alten include-Dateien werden nach include_windows kopiert."
echo "Damit das funktioniert, müssen folgende Pakete unbedingt installiert sein:"
echo " * GLEW-Entwicklungsdateien (Debian/Ubuntu: libglew-dev, Redhat/Fedora: glew-devel)"
echo " * ZLib-Entwicklungsdateien (Debian/Ubuntu: zlib-dev, Redhat/Fedora: zlib-devel)"
echo " * JPEG-Entwicklungsdateien (Debian/Ubuntu: libjpeg-dev, Redhat/Fedora: libjpeg-turbo-devel)"
echo " * XI-Entwicklungsdateien (Debian/Ubuntu: libxi-dev, Redhat/Fedora: libXi-devel)"
echo "Zum Bauen des Frameworks wird außerdem benötigt:"
echo " * Git"
echo " * Ein C++-Compiler inklusive Standardbibliotheken"
echo " * CMake"
echo "Wenn irgendwas davon fehlt, dann wird das Kompilieren fehl schlagen."
echo "Wenn Du alles richtig gemacht hast, aber trotzdem das Kompilieren nicht klappt, dann schreibe am besten"
echo "eine E-Mail an deinen Betreuer."
while true; do
read -p "Soll ich fortfahren [j/n]? " yn
case $yn in
[Jj]* ) break;;
[Nn]* ) echo "Dann eben nicht."; exit;;
* ) echo "Bitte mit j oder n antworten.";;
esac
done
git clone "https://github.com/sgumhold/cgv.git"
#Backup the old includes
mv include include_windows
# Neuen Ordner zum Kompilieren erstellen
mkdir cgv-build
cd cgv-build
# Mittels CMake Unix-Makefiles erzeugen
cmake -DBUILD_SHARED_LIBS=1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../.. ../cgv
# Makefiles kompilieren
make -j7
# Alten framework Ordner löschen
#rm -r ../framework
# Alles zusammenkopieren
make install
cd ..
# Aufraeumen
rm -r -f cgv
rm -r -f cgv-build

View file

@ -0,0 +1,34 @@
#include <cgv/base/register.h>
#include <cgv/gui/application.h>
#include <cgv/gui/gui_driver.h>
#include <cgv/gui/base_provider_generator.h>
#include <cgv/utils/file.h>
#include <cgv/base/console.h>
#include <cgv/utils/tokenizer.h>
#include <cgv/utils/advanced_scan.h>
using namespace cgv::base;
using namespace cgv::gui;
using namespace cgv::utils;
void generate_gui(gui_driver_ptr d)
{
window_ptr w = application::create_window(1280,768,"cgv 3d viewer");
w->show();
register_object(w, "register viewer window");
}
int main(int argc, char** argv)
{
cgv::base::register_prog_name(argv[0]);
connect(on_gui_driver_registration(),generate_gui);
disable_registration_event_cleanup();
enable_permanent_registration();
enable_registration();
register_object(console::get_console());
process_command_line_args(argc, argv);
enable_registration_event_cleanup();
bool res = application::run();
unregister_all_objects();
return res;
}

View file

@ -0,0 +1,210 @@
#pragma once
#include <string>
#include "group.h"
#include <cgv/type/cond/is_base_of.h>
#include "lib_begin.h"
namespace cgv {
namespace base {
class CGV_API traverse_policy;
/** The action class is used in tree traversals together with the traverser. It implements the interface needed
to perform an action on an arbitrary object. */
class CGV_API action
{
protected:
bool default_result_begin;
bool default_result_end;
public:
/// construct with default return values for the begin and end method
action(bool _default_result_begin, bool _default_result_end);
/// sets the value that is returned, whenever no result is obtained from the traversed methods
void set_default_results(bool _default_result);
/// sets the value that is returned for on_begin events
void set_default_result_begin(bool _default_result_begin);
/// sets the value that is returned for on_end events
void set_default_result_end(bool _default_result_end);
/// make the passed object current
virtual void select(base_ptr p);
/// check if the current object implements the interface needed for this action
virtual bool implements_action() const;
/// return the traverse_policy of the current object if available or 0 otherwise
virtual traverse_policy* get_policy() const;
/// perform the enter part of the action on the current object
virtual bool begin();
/// perform the leave part of the action on the current object
virtual bool end();
/// check whether the action has registered a single begin method or both begin and end methods
virtual bool has_begin_only() const;
};
template <bool is_derived, class X>
struct extract_policy_struct
{
static void extract_policy(X*, traverse_policy* &tp) { tp = 0; }
};
template <class X>
struct extract_policy_struct<true,X>
{
static void extract_policy(X* x, traverse_policy* &tp) { tp = static_cast<traverse_policy*>(x); }
};
/** base class for all actions that use methods of class X*/
template <class X>
class base_method_action : public action
{
protected:
traverse_policy* tp;
X* x;
public:
/// construct from default return values that are passed on to the base class
base_method_action(bool _default_result_begin, bool _default_result_end)
: action(_default_result_begin, _default_result_end), tp(0), x(0) {}
/// implement the select method and store pointers of type X* and traverse_policy*
void select(base_ptr p) {
x = p->get_interface<X>();
extract_policy_struct<type::cond::is_base_of<traverse_policy, X>::value,X>::extract_policy(x, tp);
}
/// simply return whether the stored pointer of type X* is not 0
bool implements_action() const {
return x != 0;
}
/// simply return the stored pointer of type traverse_policy*
traverse_policy* get_policy() const {
return tp;
}
};
/** base class for all method actions that take a single argument of type T1 in their signature*/
template <class X, typename T1>
class method_action : public base_method_action<X>
{
protected:
T1 v1;
public:
/// construct action from signature and default return values
method_action(T1 _v1, bool _default_result_begin, bool _default_result_end)
: base_method_action<X>(_default_result_begin, _default_result_end), v1(_v1) {}
/// set a new signature with which the methods of the traversed nodes are called
void set_signature(T1 _v1) { v1 = _v1; }
/// call a void method given a default return value
bool call_method(void (X::*mp)(T1), bool default_result) {
if (this->x && mp)
(this->x->*mp)(v1);
return default_result;
}
/// call a bool method given a default return value
bool call_method(bool (X::*mp)(T1), bool default_result) {
if (this->x && mp)
return (this->x->*mp)(v1);
return default_result;
}
};
/** complete implementation of method actions that only call one method when entering a node*/
template <class X, typename R, typename T1>
class single_method_action : public method_action<X,T1>
{
protected:
R (X::*on_begin)(T1);
public:
/// construct from signature, method pointer and default result values
single_method_action(T1 _v1, R (X::*_on_begin)(T1),
bool _default_result_begin = false, bool _default_result_end = false)
: method_action<X,T1>(_v1, _default_result_begin, _default_result_end), on_begin(_on_begin) {}
/// uses call_method of base class method_action to call the method refered to by the stored method pointer
bool begin() { return this->call_method(on_begin, this->default_result_begin); }
/// check whether the action has registered a single begin method or both begin and end methods
bool has_begin_only() const { return true; }
};
/** complete implementation of method actions that call a begin and end method when entering and leaving a node*/
template <class X, typename R1, typename R2, typename T1>
class matched_method_action : public method_action<X,T1>
{
protected:
R1 (X::*on_begin)(T1);
R2 (X::*on_end)(T1);
public:
/// construct from signature, method pointers and default result values
matched_method_action(T1 _v1, R1 (X::*_on_begin)(T1), R2 (X::*_on_end)(T1), bool _default_result_begin, bool _default_result_end)
: method_action<X,T1>(_v1, _default_result_begin, _default_result_end), on_begin(_on_begin), on_end(_on_end) {}
/// uses call_method of base class method_action to call the method refered to by the stored method pointer
bool begin() { return this->call_method(on_begin, this->default_result_begin); }
/// uses call_method of base class method_action to call the method refered to by the stored method pointer
bool end() { return this->call_method(on_end, this->default_result_end); }
};
/// helper function to construct an action from a signature and one method that is called when a node is entered
template <typename T1, class X, typename R>
single_method_action<X,R,T1> make_action(T1 _v1, R (X::*_on_begin)(T1), bool _default_result_begin = false, bool _default_result_end = false) {
return single_method_action<X,R,T1>(_v1, _on_begin, _default_result_begin, _default_result_end);
}
/// helper function to construct an action from a signature and two methods that are called when a node is entered and when it is left again
template <typename T1, class X, typename R1, typename R2>
matched_method_action<X,R1,R2,T1> make_action(T1 _v1, R1 (X::*_on_begin)(T1), R2 (X::*_on_end)(T1), bool _default_result_begin = false, bool _default_result_end = false) {
return matched_method_action<X,R1,R2,T1>(_v1, _on_begin, _on_end, _default_result_begin, _default_result_end);
}
/** base class for all method actions that take a single argument of type T1 in their signature*/
template <class X, typename T1, typename T2>
class method_action_2 : public base_method_action<X>
{
protected:
T1 v1;
T2 v2;
public:
/// construct action from signature and default return values
method_action_2(T1 _v1, T2 _v2, bool _default_result_begin, bool _default_result_end)
: base_method_action<X>(_default_result_begin, _default_result_end), v1(_v1), v2(_v2) {}
/// set a new signature with which the methods of the traversed nodes are called
void set_signature(T1 _v1, T2 _v2) { v1 = _v1; v2 = _v2; }
/// call a void method given a default return value
bool call_method(void (X::*mp)(T1, T2), bool default_result) {
if (this->x && mp)
(this->x->*mp)(v1,v2);
return default_result;
}
/// call a bool method given a default return value
bool call_method(bool (X::*mp)(T1, T2), bool default_result) {
if (this->x && mp)
return (this->x->*mp)(v1, v2);
return default_result;
}
};
/** complete implementation of method actions that only call one method when entering a node*/
template <class X, typename R, typename T1, typename T2>
class single_method_action_2 : public method_action_2<X,T1,T2>
{
protected:
R (X::*on_begin)(T1,T2);
public:
/// construct from signature, method pointer and default result values
single_method_action_2(T1 _v1, T2 _v2, R (X::*_on_begin)(T1,T2),
bool _default_result_begin = false, bool _default_result_end = false)
: method_action_2<X,T1,T2>(_v1, _v2, _default_result_begin, _default_result_end), on_begin(_on_begin) {}
/// uses call_method of base class method_action to call the method refered to by the stored method pointer
bool begin() { return this->call_method(on_begin, this->default_result_begin); }
/// check whether the action has registered a single begin method or both begin and end methods
bool has_begin_only() const { return true; }
};
/// helper function to construct an action from a signature and one method that is called when a node is entered
template <typename T1, typename T2, class X, typename R>
single_method_action_2<X,R,T1,T2> make_action_2(T1 _v1, T2 _v2, R (X::*_on_begin)(T1,T2), bool _default_result_begin = false, bool _default_result_end = false) {
return single_method_action_2<X,R,T1,T2>(_v1, _v2, _on_begin, _default_result_begin, _default_result_end);
}
}
}
#include <cgv/config/lib_end.h>

View file

@ -0,0 +1,53 @@
#pragma once
#include "base.h"
#include "lib_begin.h"
namespace cgv {
namespace base {
/** interface for an attachment slot that can store a base pointer */
class CGV_API attach_slot
{
protected:
/// allow to attach some object to group
base_ptr attachment;
/// allow to add user data to the attachment
void* attachment_user_data;
public:
/// init the user data
attach_slot();
/// attach object to attachment slot
void attach(base_ptr attachment_object, void* user_data = 0);
/// attach object to attachment slot
void attach(base_ptr attachment_object, int user_data);
/// return current attachment
base_ptr get_attachment() const;
/// return current attachment
void* get_attachement_data() const;
/// return current attachment
int get_attachement_data_int() const;
};
//! function to attach an object to an object of type attach_slot.
/*! Return whether the slot_object implements the attach_slot interface
and could retreive the attachment. */
extern CGV_API bool attach(base_ptr slot_object, base_ptr attachment_object, void* user_data = 0);
extern CGV_API bool attach(base_ptr slot_object, base_ptr attachment_object, int user_data);
//! query the attachment of an attach_slot object.
/*! If the slot_object is not derived from the attach_slot interface,
return an empty base_ptr. */
extern CGV_API base_ptr get_attachment(base_ptr slot_object);
//! query the user data of the attachment of an attach_slot object.
/*! If the slot_object is not derived from the attach_slot interface,
return the null pointer. */
extern CGV_API void* get_attachment_data(base_ptr slot_object);
extern CGV_API int get_attachment_data_int(base_ptr slot_object);
}
}
#include <cgv/config/lib_end.h>

View file

@ -0,0 +1,194 @@
#pragma once
#include <cgv/type/info/type_name.h>
#include <cgv/reflect/reflection_handler.h>
#include <cgv/data/ref_ptr.h>
#include <iostream>
#include <cgv/type/lib_begin.h>
namespace cgv {
namespace type {
namespace info {
struct CGV_API type_interface;
/// pointer to const type interface
typedef cgv::data::ref_ptr<const type_interface,true> const_type_ptr;
}
}
}
#include <cgv/config/lib_end.h>
#include "lib_begin.h"
/// the cgv namespace
namespace cgv {
/// the base namespace holds the base hierarchy, support for plugin registration and signals
namespace base {
class CGV_API base;
class CGV_API named;
class CGV_API node;
class CGV_API group;
/// ref counted pointer to base
typedef data::ref_ptr<base,true> base_ptr;
struct cast_helper_base
{
template <class T>
static data::ref_ptr<T,true> cast_of_base(base* b);
};
template <class T>
struct cast_helper : public cast_helper_base
{
inline static data::ref_ptr<T,true> cast(base* b)
{
return cast_of_base<T>(b);
}
};
/** base class for all classes that can be registered with support
for dynamic properties (see also section \ref baseSEC of page \ref baseNS). */
class CGV_API base : public data::ref_counted, public cgv::reflect::self_reflection_tag
{
protected:
/// give ref_ptr access to destructor
friend class data::ref_ptr_impl<base,true>;
/// make destructor virtual and not accessible from outside
virtual ~base();
/// give cast_helper_base access to cast_dynamic
friend struct cast_helper_base;
/// use dynamic cast for upcast to given class
template <class T>
inline static data::ref_ptr<T,true> cast_dynamic(base* b)
{
return data::ref_ptr<T,true>(dynamic_cast<T*>(b));
}
public:
/// overload to return the type name of this object. By default the type interface is queried over get_type.
virtual std::string get_type_name() const;
/// overload to handle register events that is sent after the instance has been registered
virtual void on_register();
/// overload to handle unregistration of instances
virtual void unregister();
/// overload to show the content of this object
virtual void stream_stats(std::ostream&);
/// cast upward to named
virtual data::ref_ptr<named,true> get_named();
/// cast upward to node
virtual data::ref_ptr<node,true> get_node();
/// cast upward to group
virtual data::ref_ptr<group,true> get_group();
/// cast to arbitrary class, but use the casts to named, node and group from the interface
template <class T>
data::ref_ptr<T,true> cast() {
return cast_helper<T>::cast(this);
}
/// use dynamic type cast to check for the given interface
template <class T>
T* get_interface() {
return dynamic_cast<T*>(this);
}
/// use dynamic type cast to check for the given interface
template <class T>
const T* get_const_interface() const {
return dynamic_cast<const T*>(this);
}
/// this virtual update allows for example to ask a view to update the viewed value. The default implementation is empty.
virtual void update();
/// this virtual method allows to pass application specific data for internal purposes
virtual void* get_user_data() const;
/**@name property interface*/
//@{
//! used for simple self reflection
/*! The overloaded implementation is used by the default implementations of
set_void, get_void and get_property_declarations
with corresponding reflection handlers.
The default implementation of self_reflect is empty. */
virtual bool self_reflect(cgv::reflect::reflection_handler&);
//! return a semicolon separated list of property declarations
/*! of the form "name1:type1;name2:type2;...", by default an empty
list is returned. The types should by consistent with the names
returned by cgv::type::info::type_name::get_name. The default
implementation extracts names and types from the self_reflect()
method and the meta type information provided by the get_type()
method. */
virtual std::string get_property_declarations();
//! abstract interface for the setter of a dynamic property.
/*! The default implementation
uses the self_reflect() method to find a member with the given property as name. If
not found, the set_void method returns false. */
virtual bool set_void(const std::string& property, const std::string& value_type, const void* value_ptr);
/// this callback is called when the set_void method has changed a member and can be overloaded in derived class
virtual void on_set(void* member_ptr);
//! abstract interface for the getter of a dynamic property.
/*! The default implementation
uses the self_reflect() method to find a member with the given property as name. If
not found, the get_void method returns false. */
virtual bool get_void(const std::string& property, const std::string& value_type, void* value_ptr);
//! abstract interface to call an action
/*! , i.e. a class method based on the action name and
the given parameters. The default implementation uses the self_reflect() method to
dispatch this call. If not found, the get_void method returns false.*/
virtual bool call_void(const std::string& method,
const std::vector<std::string>& param_value_types,
const std::vector<const void*>& param_value_ptrs,
const std::string& result_type = "",
void* result_value_ptr = 0);
//! specialization of set method to support const char* as strings
void set(const std::string& property, const char* value) { const std::string& s(value); set_void(property, cgv::type::info::type_name<std::string>::get_name(), &s); }
//! set a property of the element to the given value and perform standard conversions if necessary.
/*! This templated version simply extracts the type of the value from the
reference and calls the set_void() method. Note that this only works if the template
cgv::type::info::type_name<T> is overloaded for the value type. */
template <typename T>
void set(const std::string& property, const T& value) { set_void(property, cgv::type::info::type_name<T>::get_name(), &value); }
//! query a property of the element and perform standard conversions if necessary.
/*! This templated version simply extracts the type of the value from the
reference and calls the set_void() method. Note that this only works if the template
cgv::type::info::type_name<T> is overloaded for the value type. */
template <typename T>
T get(const std::string& property) { T value; get_void(property, cgv::type::info::type_name<T>::get_name(), &value); return value; }
//! set several properties
/*! , which are defined as colon separated assignments,
where the types are derived automatically to bool, int,
double or std::string. */
void multi_set(const std::string& property_assignments, bool report_error = true);
//! check if the given name specifies a property.
/*! If the type name string pointer is provided, the type of the
property is copied to the referenced string. */
bool is_property(const std::string& property_name, std::string* type_name = 0);
//! find a member pointer by name.
/*! If not found the null pointer is returned. If the type name
string pointer is provided, the type of the
property is copied to the referenced string.*/
void* find_member_ptr(const std::string& property_name, std::string* type_name = 0);
//@}
};
template <typename T>
inline data::ref_ptr<T,true> cast_helper_base::cast_of_base(base* b)
{
return base::cast_dynamic<T>(b);
}
#if _MSC_VER > 1400
#pragma warning(disable:4275)
#pragma warning(disable:4231)
#pragma warning(disable:4251)
CGV_TEMPLATE template class CGV_API cgv::data::ref_ptr<cgv::base::base>;
CGV_TEMPLATE template class CGV_API std::vector<cgv::data::ref_ptr<cgv::base::base> >;
#endif
}
}
#include <cgv/config/lib_end.h>

View file

@ -0,0 +1,140 @@
#pragma once
#include "base.h"
#include <cgv/type/variant.h>
#include <map>
#include "lib_begin.h"
using namespace cgv::type;
/// the cgv namespace
namespace cgv {
/// the base namespace holds the base hierarchy, support for plugin registration and signals
namespace base {
struct CGV_API abst_property_access
{
bool has_changed;
abst_property_access();
virtual const char* get_type_name() const = 0;
virtual bool set(const std::string& value_type, const void* value_ptr) = 0;
virtual bool get(const std::string& value_type, void* value_ptr) = 0;
};
template <typename T>
struct standard_type_property_access : public abst_property_access
{
T* ptr;
standard_type_property_access(T* _ptr) : ptr(_ptr) {}
const char* get_type_name() const { return cgv::type::info::type_name<T>::get_name(); }
bool set(const std::string& value_type, const void* value_ptr) { get_variant(*ptr,value_type,value_ptr); has_changed = true; return true; }
bool get(const std::string& value_type, void* value_ptr) { set_variant(*ptr,value_type,value_ptr); return true; }
};
template <typename T>
struct emulated_property_access : public abst_property_access
{
T* ptr;
emulated_property_access(T* _ptr) : ptr(_ptr) {}
const char* get_type_name() const { return cgv::type::info::type_name<T>::get_name(); }
bool set(const std::string& value_type, const void* value_ptr) {
if (value_type == get_type_name()) {
*ptr = *((const T*) value_ptr);
has_changed = true;
return true;
}
else if (value_type == "string") {
return has_changed = cgv::utils::from_string(*ptr, *((std::string*)value_ptr));
}
return false;
}
bool get(const std::string& value_type, void* value_ptr) {
if (value_type == get_type_name()) {
*((T*) value_ptr) = *ptr;
return true;
}
else if (value_type == "string") {
*((std::string*)value_ptr) = cgv::utils::to_string(*ptr);
}
return false;
}
};
template <typename T>
struct property_access : public emulated_property_access<T>
{
property_access(T* _ptr) : emulated_property_access<T>(_ptr) {}
};
template <> struct property_access<int8_type> : public standard_type_property_access<int8_type> { property_access<int8_type>( int8_type* _ptr) : standard_type_property_access<int8_type>(_ptr) {}; };
template <> struct property_access<int16_type> : public standard_type_property_access<int16_type> { property_access<int16_type>(int16_type* _ptr) : standard_type_property_access<int16_type>(_ptr) {}; };
template <> struct property_access<int32_type> : public standard_type_property_access<int32_type> { property_access<int32_type>(int32_type* _ptr) : standard_type_property_access<int32_type>(_ptr) {}; };
template <> struct property_access<int64_type> : public standard_type_property_access<int64_type> { property_access<int64_type>(int64_type* _ptr) : standard_type_property_access<int64_type>(_ptr) {}; };
template <> struct property_access<uint8_type> : public standard_type_property_access<uint8_type> { property_access<uint8_type>( uint8_type* _ptr) : standard_type_property_access<uint8_type>(_ptr) {}; };
template <> struct property_access<uint16_type> : public standard_type_property_access<uint16_type> { property_access<uint16_type>(uint16_type* _ptr) : standard_type_property_access<uint16_type>(_ptr) {}; };
template <> struct property_access<uint32_type> : public standard_type_property_access<uint32_type> { property_access<uint32_type>(uint32_type* _ptr) : standard_type_property_access<uint32_type>(_ptr) {}; };
template <> struct property_access<uint64_type> : public standard_type_property_access<uint64_type> { property_access<uint64_type>(uint64_type* _ptr) : standard_type_property_access<uint64_type>(_ptr) {}; };
template <> struct property_access<float> : public standard_type_property_access<float> { property_access<float>(float* _ptr) : standard_type_property_access<float>(_ptr) {}; };
template <> struct property_access<double> : public standard_type_property_access<double> { property_access<double>(double* _ptr) : standard_type_property_access<double>(_ptr) {}; };
template <> struct property_access<bool> : public standard_type_property_access<bool> { property_access<bool>(bool* _ptr) : standard_type_property_access<bool>(_ptr) {}; };
template <> struct property_access<std::string> : public standard_type_property_access<std::string> { property_access<std::string>(std::string* _ptr) : standard_type_property_access<std::string>(_ptr) {}; };
/** implements a dynamic object, that can be composed of independent variables, which are
handled as properties of the base_generator and published through the property interface
of the base class. */
class CGV_API base_generator : public cgv::base::base
{
protected:
typedef std::map<std::string,abst_property_access*> map_type;
typedef map_type::iterator iter_type;
typedef map_type::const_iterator const_iter_type;
/// store the properties as map from property name to type and pointer to instance
map_type property_map;
public:
/// overload to return the type name of this object. By default the type interface is queried over get_type.
std::string get_type_name() const;
/// add a new property
void add_void(const std::string& name, abst_property_access* apa);
/// add a property by deriving property access from type of reference value
template <typename T>
void add(const std::string& property, T& value) { add_void(property, new property_access<T>(&value)); }
/// remove a property
void del(const std::string& property);
/// return whether property has changed
bool changed(const std::string& property) const;
//! returns a semicolon separated list of property declarations
std::string get_property_declarations();
//! abstract interface for the setter of a dynamic property.
bool set_void(const std::string& property, const std::string& value_type, const void* value_ptr);
//! abstract interface for the getter of a dynamic property.
bool get_void(const std::string& property, const std::string& value_type, void* value_ptr);
};
//! simple parsing support to access values of properties in a string of property assignment
/*! Given an option string (first parameter) with name-value-pairs, i.e. "x=10.4;tooltip='help'"
and a property name (second parameter), the function returns whether the option string contains
an assignment of the queried property and if yes, the value is stored in the reference given
in the third parameter. The type casts supported by the cgv::type::variant type are used when
converting to the reference type.
Examples:
true == has_property("x=10.4;tooltip='help'", "x", dbl_var)" ==> dbl_var = 10.4
true == has_property("x=10.4;tooltip='help'", "x", str_var)" ==> str_var = "10.4"
true == has_property("x=10.4;tooltip='help'", "tooltip", str_var)" ==> str_var = "help"
false == has_property("x=10.4;tooltip='help'", "y", int_var)" ==> int_var ... not changed
*/
template <typename T>
bool has_property(const std::string& options, const std::string& property, T& value, bool report_error = true) {
base_generator bg;
bg.add(property, value);
bg.multi_set(options, report_error);
return bg.changed(property);
}
}
}
#include <cgv/config/lib_end.h>

View file

@ -0,0 +1,40 @@
#pragma once
#include <cgv/base/base.h>
#include <cgv/data/ref_ptr.h>
#include "lib_begin.h"
namespace cgv {
namespace base {
class console;
/// pointer to console
typedef cgv::data::ref_ptr<console,true> console_ptr;
/** interface to the console of the application with implementation
of the property interface */
class CGV_API console : public cgv::base::base
{
private:
/// hide constructor for singleton protection
console();
public:
/// return console singleton
static console_ptr get_console();
/// return "console"
std::string get_type_name() const;
/// supported properties are x:int32;y:int32;w:int32;h:int32;show:bool;title:string
std::string get_property_declarations();
///
bool set_void(const std::string& property, const std::string& value_type, const void* value_ptr);
///
bool get_void(const std::string& property, const std::string& value_type, void* value_ptr);
};
}
}
#include <cgv/config/lib_end.h>

View file

@ -0,0 +1,44 @@
#pragma once
#include <cgv/base/action.h>
namespace cgv {
namespace base {
/// simple action implementation that adds nodes implementing X to a results vector
template <class X>
class find_action : public action
{
X* x;
protected:
std::vector<X*>& result;
public:
find_action(std::vector<X*>& _result) : action(true,true), result(_result) {}
/// make the passed object current
void select(base_ptr p) {
x = p->get_interface<X>();
}
bool begin()
{
if (x) {
result.push_back(x);
return true;
}
else
return false;
}
/// check if the current object implements the interface needed for this action
bool implements_action() const {
return x != 0;
}
};
/// collect all nodes that implement interface X
template <class X>
void find_interface(base_ptr start, std::vector<X*>& result) {
find_action<X> fa(result);
traverser(fa).traverse(start);
}
}
}

View file

@ -0,0 +1,67 @@
#pragma once
#include "node.h"
#include <vector>
#include "lib_begin.h"
namespace cgv {
namespace base {
class CGV_API group;
/// ref counted pointer to a node
typedef data::ref_ptr<group,true> group_ptr;
/** The group class is a node with children. */
class CGV_API group : public node
{
protected:
/// declare group_ptr to be a friend class
friend class data::ref_ptr<group,true>;
/// store a list of children
std::vector<base_ptr> children;
/// check if the base class is a node and set the parent of the node
void link(base_ptr b);
/// check if the base class is a node and clear the parent of the node
void unlink(base_ptr b);
public:
/// construct from name
group(const std::string& name = "");
/// return the number of children
unsigned int get_nr_children() const;
/// return the i-th child
base_ptr get_child(unsigned int i) const;
/// append child and return index of appended child
virtual unsigned int append_child(base_ptr child);
/// remove all elements of the vector that point to child, return the number of removed children
virtual unsigned int remove_child(base_ptr child);
/// remove all children
virtual void remove_all_children();
/// insert a child at the given position
virtual void insert_child(unsigned int i, base_ptr child);
/// cast upward to group
data::ref_ptr<group,true> get_group();
/// overload to return the type name of this object
std::string get_type_name() const;
};
template <>
struct cast_helper<group>
{
inline static data::ref_ptr<group,true> cast(base* b)
{
return b->get_group();
}
};
#if _MSC_VER >= 1400
CGV_TEMPLATE template class CGV_API data::ref_ptr<group>;
CGV_TEMPLATE template class CGV_API std::vector<base_ptr>;
#endif
}
}
#include <cgv/config/lib_end.h>

View file

@ -0,0 +1,62 @@
#pragma once
#include <string>
#include <vector>
#include "lib_begin.h"
///
namespace cgv {
///
namespace base {
/// extract a valid path from the given argument and push it onto the stack of parent paths. This should always be paired with a call to pop_file_parent().
extern CGV_API void push_file_parent(const std::string& path_or_file_name);
/// pop the latestly pushed parent path from the parent path stack.
extern CGV_API void pop_file_parent();
/** Find a file with the given strategy and return the file name extended by the necessary path.
The strategy defines in which search paths the file should be looked for, whether the search
paths should be searched recursively and in which order the search paths should be searched
(see details below).
Optional arguments are a sub_directory and a master_path. For all non recursive searches the
sub_directory will be added to each search path and the file is first looked up in the sub_directory.
The master_path just defines another search path that can be used by the search strategy.
The search strategy is a string containing one letter for each search command, which are processed
in the order of the string. Each capital letter causes a recursive search. The following search
commands are available:
- r/R ... search resource files (no recursive search necessary as resource files do not have paths) and if found add the prefix "res://" to the file_name
- c/C ... search current directory (here no path prefix is used)
- m/M ... search master path
- d/D ... search all data paths registered in the environment variable CGV_DATA
- p/P ... search the path of the parent on the parent path stack that is controlled with push_file_parent() and pop_file_parent()
- a/A ... search all anchester paths of the all parents on the parent path stack that is controlled with push_file_parent() and pop_file_parent()
As an example the strategy "cpmD" first looks in the current directory, then in the parent directory, then in the master path and finally recursively
in each of the registered data paths.
*/
extern CGV_API std::string find_data_file(const std::string& file_name, const std::string& strategy, const std::string& sub_directory = "", const std::string& master_path = "");
/// return a reference to the data path list, which is constructed from the environment variable CGV_DATA
extern CGV_API std::vector<std::string>& ref_data_path_list();
/// return a reference to the parent file stack controlled with push_file_parent() and pop_file_parent(), where the last vector element is the latestly pushed one
extern CGV_API std::vector<std::string>& ref_parent_file_stack();
/// open a file with fopen supporting resource files, that have the prefix "res://"
extern CGV_API FILE* open_data_file(const std::string& file_name, const char* mode);
/// read ascii file into a string
extern CGV_API bool read_data_file(const std::string& file_name, std::string& content, bool ascii);
/// return the file size of a given file with support for resource files, that have the prefix "res://"
extern CGV_API unsigned int data_file_size(const std::string& file_name);
/// find the offset of the given data block in the given file
extern CGV_API unsigned int find_file_offset(const std::string& file_name, const char* data, unsigned int data_size);
}
}
#include <cgv/config/lib_end.h>

View file

@ -0,0 +1,8 @@
#if defined(CGV_BASE_FORCE_STATIC)
# define CGV_FORCE_STATIC_LIB
#endif
#ifdef CGV_BASE_EXPORTS
# define CGV_EXPORTS
#endif
#include <cgv/config/lib_begin.h>

View file

@ -0,0 +1,52 @@
#pragma once
#include "base.h"
#include "lib_begin.h"
namespace cgv {
namespace base {
class CGV_API named;
/// ref counted pointer to a node
typedef data::ref_ptr<named,true> named_ptr;
/** base class for all gui types */
class CGV_API named : public base
{
protected:
/// declare named_ptr to be a friend class
friend class data::ref_ptr<named,true>;
/// store the name as a string
std::string name;
public:
/// construct from name
named(const std::string& name = "");
/// return the parent node
const std::string& get_name() const;
/// set a new parent node
void set_name(const std::string& _name);
/// cast upward to named
data::ref_ptr<named,true> get_named();
/// overload to return the type name of this object
std::string get_type_name() const;
};
template <>
struct cast_helper<named>
{
inline static data::ref_ptr<named,true> cast(base* b)
{
return b->get_named();
}
};
#if _MSC_VER >= 1400
CGV_TEMPLATE template class CGV_API data::ref_ptr<named>;
#endif
}
}
#include <cgv/config/lib_end.h>

View file

@ -0,0 +1,54 @@
#pragma once
#include <cgv/data/ref_ptr.h>
#include "named.h"
#include "lib_begin.h"
namespace cgv {
namespace base {
class CGV_API node;
/// ref counted pointer to a node
typedef data::ref_ptr<node,true> node_ptr;
/** The node class keeps a pointer to its parent */
class CGV_API node : public named
{
protected:
/// declare node_ptr to be a friend class
friend class data::ref_ptr<node,true>;
/// store a pointer to the parent node
node_ptr parent;
public:
/// construct from name
node(const std::string& name = "");
/// return the parent node
node_ptr get_parent() const;
/// return the root node by traversing parents until no more parent is available
base_ptr get_root() const;
/// set a new parent node
void set_parent(node_ptr _parent);
/// cast upward to node
data::ref_ptr<node,true> get_node();
/// overload to return the type name of this object
std::string get_type_name() const;
};
template <>
struct cast_helper<node>
{
inline static data::ref_ptr<node,true> cast(base* b)
{
return b->get_node();
}
};
#if _MSC_VER >= 1400
CGV_TEMPLATE template class CGV_API data::ref_ptr<node>;
#endif
}
}
#include <cgv/config/lib_end.h>

View file

@ -0,0 +1,505 @@
#pragma once
#include <cgv/base/base.h>
#include <cgv/base/named.h>
#include <string>
#include <iostream>
#include <map>
#include "lib_begin.h"
#ifndef _WIN32
#include <unistd.h>
#include <dlfcn.h>
#endif
/// the cgv namespace
namespace cgv {
/// the base namespace holds the base hierarchy, support for plugin registration and signals
namespace base {
/**@name control over the registration process */
//@{
//! Enable registration (default is that registration is disabled).
/*! If registration has been disabled before, send all registration events that
where emitted during disabled registration. */
extern void CGV_API enable_registration();
/// if registration is disable, all registration events are stored and sent at the momement when registration is enabled again. This feature is used when loading dlls
extern void CGV_API disable_registration();
/// check whether registration is enabled
extern bool CGV_API is_registration_enabled();
/// enable registration debugging
extern void CGV_API enable_registration_debugging();
/// disable registration debugging
extern void CGV_API disable_registration_debugging();
/// check whether registration debugging is enabled
extern bool CGV_API is_registration_debugging_enabled();
/// register a registration listener that stores pointers to all registered objects
extern void CGV_API enable_permanent_registration();
/// deregister registration listener and dereference pointers to registered objects
extern void CGV_API disable_permanent_registration();
/// check whether permanent registration is enabled
extern bool CGV_API is_permanent_registration_enabled();
/// unregister all existing objects to clean up
extern void CGV_API unregister_all_objects();
/// access to number of permanently registered objects
extern unsigned CGV_API get_nr_permanently_registered_objects();
/// access to i-th permanently registered object
extern base_ptr CGV_API get_permanently_registered_object(unsigned i);
//! Enable cleanup of registration events (default).
/*! If registration event cleanup is disabled, registration events are not
discarded as soon as objects have been registered. This makes objects
available to listeners that are registered later. */
extern void CGV_API enable_registration_event_cleanup();
/// disable cleanup of registration events (see enable_registration_event_cleanup).
extern void CGV_API disable_registration_event_cleanup();
/// return whether registration cleanup is enabled
extern bool CGV_API is_registration_event_cleanup_enabled();
//@}
/**@name object registration */
//@{
//! register an object.
/*! This will send an event to all currently registered registration listeners. The options parameter
can be used to select a specific listener. */
extern void CGV_API register_object(base_ptr object, const std::string& options = "");
/// unregister an object and send event to all currently registered registration listeners
extern void CGV_API unregister_object(base_ptr object, const std::string& options = "");
// abstract base class of helpers to perform delayed registration and creation of objects in case that the registration is currently disabled
struct CGV_API object_constructor : public cgv::base::base
{
public:
// creation function
virtual base_ptr construct_object() const = 0;
};
// type specific specialization of helper class to perform delayed registration and creation of objects in case that the registration is disabled
template <class T>
class object_constructor_impl : public object_constructor
{
public:
// creation function
base_ptr construct_object() const { return base_ptr(new T()); }
};
// type specific specialization of helper class to perform delayed registration and creation of objects in case that the registration is disabled
template <class T, typename CA>
class object_constructor_impl_1 : public object_constructor
{
// buffer constructor argument
CA ca;
public:
// construct from option
object_constructor_impl_1(const CA& _ca) : ca(_ca) {}
// creation function
base_ptr construct_object() const { return base_ptr(new T(ca)); }
};
// type specific specialization of helper class to perform delayed registration and creation of objects in case that the registration is disabled
template <class T, typename CA1, typename CA2>
class object_constructor_impl_2 : public object_constructor
{
// buffer constructor arguments
CA1 ca1;
CA2 ca2;
public:
// construct from option
object_constructor_impl_2(const CA1& _ca1, const CA2& _ca2) : ca1(_ca1), ca2(_ca2) {}
// creation function
base_ptr construct_object() const { return base_ptr(new T(ca1,ca2)); }
};
/// convenience class to register an object of the given class type
template <class T>
struct object_registration
{
/// pass information about the target registration listener in the options argument
object_registration(const std::string& options) {
if (is_registration_enabled())
register_object(base_ptr(new T()),options);
else
register_object(base_ptr(new object_constructor_impl<T>()), options);
}
};
/// convenience class to register an object of the given class type with one constructor argument
template <class T, typename CA>
struct object_registration_1
{
/// pass information about the target registration listener in the options argument
object_registration_1(const CA& arg, const std::string& options = "") {
if (is_registration_enabled())
register_object(base_ptr(new T(arg)),options);
else
register_object(base_ptr(new object_constructor_impl_1<T,CA>(arg)), options);
}
};
/// convenience class to register an object of the given class type with two constructor arguments
template <class T, typename CA1, typename CA2>
struct object_registration_2
{
/// pass information about the target registration listener in the options argument
object_registration_2(const CA1& a1, const CA2& a2, const std::string& options = "")
{
if (is_registration_enabled())
register_object(base_ptr(new T(a1,a2)),options);
else
register_object(base_ptr(new object_constructor_impl_2<T,CA1,CA2>(a1,a2)),options);
}
};
//@}
/**@name support for driver, listener and factory registration*/
//@{
//! interfaces that add provides very basic functionality.
/*! Servers are registered before drivers and before listeners. */
struct CGV_API server
{
};
//! interfaces that add several listeners and objects.
/*! Drivers are special classes that provide extended functionality. They are registered
after servers and before listeners. */
struct CGV_API driver
{
};
//! interfaces that allows to listen to registration events.
/*! In order to allow registration of a registration listener, the implementation must
also inherit cgv::base::base. When registration had been disabled and is enabled again,
registration listeners are registered before all other objects. */
struct CGV_API registration_listener
{
/// overload to handle registration events
virtual void register_object(base_ptr object, const std::string& options = "") = 0;
/// overload to handle unregistration events
virtual void unregister_object(base_ptr object, const std::string& options = "") = 0;
};
//! interface for a factory that allows to create objects derived from cgv::base::base
struct CGV_API factory : public base
{
protected:
/// store the type name of the to be created objects
std::string created_type_name;
/// store whether the factory can only create one object
bool is_singleton;
/// pointer to the single object created by the factory in case is_singelton is true
base_ptr singleton;
/// store the options used for registering newly created objects
std::string object_options;
public:
/// construct
factory(const std::string& _created_type_name, bool _singleton = false, const std::string& _object_options = "");
/// return the options string used for object registration
virtual std::string get_object_options() const;
/// overload to return the type name of the objects that the factory can create
const std::string& get_created_type_name() const;
/// support creation of object by setting create property to true
std::string get_property_declarations();
///
bool set_void(const std::string& property, const std::string& value_type, const void* value_ptr);
///
bool get_void(const std::string& property, const std::string& value_type, void* value_ptr);
/// return whether the factory can only generate one instance of the given type
bool is_singleton_factory() const;
/// return pointer to singleton
base_ptr get_singleton() const;
/// release the singleton pointer
void release_singleton();
/// overload to create an object
base_ptr create_object();
/// overload to create an object
virtual base_ptr create_object_impl() = 0;
};
/// implementation of factory for objects of type T using the standard constructor
template <class T>
struct factory_impl : public factory
{
inline factory_impl(const std::string& _created_type_name, bool _is_singleton = false, const std::string& _object_options = "") :
factory(_created_type_name, _is_singleton, _object_options) {}
inline base_ptr create_object_impl() { return base_ptr(new T()); }
std::string get_type_name() const { return std::string("factory_impl<")+get_created_type_name()+">"; }
};
/// implementation of factory for objects of type T using a constructor with one argument of type CA
template <class T, typename CA>
struct factory_impl_1 : public factory
{
CA ca;
inline factory_impl_1(CA _ca, const std::string& _created_type_name, bool is_singleton = false, const std::string& _object_options = "") :
factory(_created_type_name, is_singleton, _object_options), ca(_ca) {}
inline base_ptr create_object_impl() { return base_ptr(new T(ca)); }
std::string get_type_name() const { return std::string("factory_impl_1<")+get_created_type_name()+">"; }
};
/// implementation of factory for objects of type T using a constructor with two arguments of types CA1 and CA2
template <class T, typename CA1, typename CA2>
struct factory_impl_2 : public factory
{
CA1 ca1;
CA2 ca2;
inline factory_impl_2(CA1 _ca1, CA2 _ca2, const std::string& _created_type_name, bool is_singleton = false, const std::string& _object_options = "") :
factory(_created_type_name, is_singleton, _object_options), ca1(_ca1), ca2(_ca2) {}
inline base_ptr create_object_impl() { return base_ptr(new T(ca2)); }
std::string get_type_name() const { return std::string("factory_impl_2<")+get_created_type_name()+">"; }
};
extern std::string CGV_API guess_created_type_name(const char* item_text);
extern void CGV_API register_factory_object(base_ptr fo, const char* item_text, char shortcut);
/// convenience class to register a factory of the given class type
template <class T>
struct factory_registration
{
//! this registers an instance of the default factory implementation
/*! parameters:
- \c _created_type_name ... name of the type of the instances created by the factory
- \c _options ... semicolon separated options used to register the factory. For gui
integration these can include assignments to "menu_path" and "shortcut"
- \c _is_singleton ... whether the factory can create only one instance
- \c _object_options ... options used to register created instances
*/
factory_registration(const std::string& _created_type_name, const std::string& _options = "", bool _is_singleton = false, const std::string& _object_options = "") {
register_object(new factory_impl<T>(_created_type_name, _is_singleton, _object_options), _options);
}
//! this constructor is only provided for downward compatibility and should not be used anymore.
/*! Item text and shortcut can be specified in the option string via
"menu_path=\"geometry/sphere\";shortcut='Q'". */
factory_registration(const char* item_text, char shortcut, bool is_singleton = false) {
register_factory_object(new factory_impl<T>(guess_created_type_name(item_text), is_singleton), item_text, shortcut);
}
};
/// convenience class to register a factory of the given class type that uses a constructor with one argument of type CA
template <class T, typename CA>
struct factory_registration_1
{
//! this registers an instance of a standard factory implementation
/*! parameters:
- \c _ca ... argument passed to the constructor of the created instances
- \c _created_type_name ... name of the type of the instances created by the factory
- \c _options ... semicolon separated options used to register the factory. For gui
integration these can include assignments to "menu_path" and "shortcut"
- \c _is_singleton ... whether the factory can create only one instance
- \c _object_options ... options used to register created instances
*/
factory_registration_1(const std::string& _created_type_name, const CA& _ca, const std::string& _options = "", bool _is_singleton = false, const std::string& _object_options = "") {
register_object(new factory_impl_1<T,CA>(_ca, _created_type_name, _is_singleton, _object_options), _options);
}
//! this constructor is only provided for downward compatibility and should not be used anymore.
/*! Item text and shortcut can be specified in the option string via
"menu_path=\"geometry/sphere\";shortcut='Q'". */
factory_registration_1(const char* item_text, char shortcut, const CA& _ca, bool is_singleton = false) {
register_factory_object(new factory_impl_1<T,CA>(_ca, guess_created_type_name(item_text), is_singleton), item_text, shortcut);
}
};
/// convenience class to register a factory of the given class type that uses a constructor with one argument of type CA
template <class T, typename CA1, typename CA2>
struct factory_registration_2
{
//! this registers an instance of a standard factory implementation
/*! parameters:
- \c _ca1, \c _ca2 ... arguments passed to the constructor of the created instances
- \c _created_type_name ... name of the type of the instances created by the factory
- \c _options ... semicolon separated options used to register the factory. For gui
integration these can include assignments to "menu_path" and "shortcut"
- \c _is_singleton ... whether the factory can create only one instance
- \c _object_options ... options used to register created instances
*/
factory_registration_2(const std::string& _created_type_name, const CA1& _ca1, const CA2& _ca2, const std::string& _options = "", bool _is_singleton = false, const std::string& _object_options = "") {
register_object(new factory_impl_2<T,CA1,CA2>(_ca1, _ca2, _created_type_name, _is_singleton, _object_options), _options);
}
};
//@}
/**@name test registration */
//@{
/// structure used to register a test function
class CGV_API test : public base
{
public:
/// static counter for all tests
static int nr_failed;
protected:
/// name of test function
std::string test_name;
/// pointer to test function
bool (*test_func)();
public:
/// constructor for a test structure
test(const std::string& _test_name, bool (*_test_func)());
/// implementation of the type name function of the base class
std::string get_type_name() const;
/// access to name of test function
std::string get_test_name() const;
/// execute test and return whether this was successful
bool exec_test() const;
};
/// use this macro in a test function to check whether expression V is true
#define TEST_ASSERT(V) \
if (!(V)) { \
std::cerr << "\n" << __FILE__ << "(" << __LINE__ << ") : error: test failure" << std::endl; \
++cgv::base::test::nr_failed; \
}
/// use this macro in a test function to check whether the two expression V and Q are equal
#define TEST_ASSERT_EQ(V,Q) \
if ((V) != (Q)) { \
std::cerr << "\n" << __FILE__ << "(" << __LINE__ << ") : error: test failure " << (V) << "!=" << (Q) << std::endl; \
++cgv::base::test::nr_failed; \
}
/// declare an instance of test_registration as static variable in order to register a test function in a test plugin
struct CGV_API test_registration
{
/// the constructor creates a test structure and registeres the test
test_registration(const std::string& _test_name, bool (*_test_func)());
};
//@}
/**@name resource file registration */
//@{
/// information registered with each resource file
struct CGV_API resource_file_info
{
/// at which location the resource file starts within the executable or dll
unsigned int file_offset;
/// length of the resource file in bytes
unsigned int file_length;
/// pointer to
const char* file_data;
/// name of
std::string source_file;
/// construct resource file info
resource_file_info(
unsigned int _file_offset = 0,
unsigned int _file_length = 0,
const char* _file_data = 0,
const std::string& _source_file = "");
};
/// return a reference to a mapping of resource file names to resource file infos
extern CGV_API std::map<std::string, resource_file_info>& ref_resource_file_map();
/// register a resource file
extern CGV_API void register_resource_file(const std::string& file_path, unsigned int file_offset, unsigned int file_length, const char* file_data, const std::string& source_file = "");
/// convenience class to register a resource file
struct CGV_API resource_file_registration
{
/// builds a resource file info and registers it with the register_resource_file function
resource_file_registration(const char* symbol);
};
//@}
/**@name processing of commands*/
//@{
//! process a command.
/*! Return whether the command was processed correctly. If eliminate_quotes is
set to true, quotes around the command arguments are eliminated. This feature
is used for commands specified on the command line, where spaces in the command
arguments would split one command into pieces. Quotes are used then to protect the
command from splitting.
The following commands are supported:
- show all ... print out information on all registered objects
- plugin:file_name ... read a plugin
- config:file_name ... read a config file
- gui:file_name ... read a gui description file
- name(xxx):assignment list ... find registered object by name xxx and process assignments on them
- type(yyy):assignment list ... find registered object by type yyy and process assignments on them
The assigment list in the name and type commands are of the form:
member_name_1=value_1;member_name_2=value_2;...
*/
extern bool CGV_API process_command(const std::string& cmd, bool eliminate_quotes = true);
/// show information about all registered members
extern void CGV_API show_all();
//@}
/**@name processing of command line arguments*/
//@{
//! set the file name of the current program.
/*! simply pass argv[0] in the main procedure. This is done automatically in the
process_command_line_args function.*/
extern CGV_API void register_prog_name(const char* prog_name);
/// return a refence to the name of the started executable
extern CGV_API std::string& ref_prog_name();
/// process the command line arguments: extract program name and load all plugins
extern CGV_API void process_command_line_args(int argc, char** argv);
//@}
/**@name configuration and gui files*/
//@{
//! abstract interface for observers of config files.
/*! The typically used implementation is found in the cgv_gui library.*/
struct config_file_observer
{
/// to be implemented method that adds permanent registration for a list of property assignments
virtual void multi_observe(base_ptr bp, const std::string& property_assignments, unsigned off) = 0;
};
//! abstract interface for a config file driver that handles permanent registration and gui config files.
/*! The typically used implementation is found in the cgv_gui library.*/
struct config_file_driver
{
public:
/// create or find a config_file_observer from the given file name and the read content of the config file
virtual config_file_observer* find_config_file_observer(const std::string& file_name, const std::string& content) = 0;
/// process a gui file
virtual bool process_gui_file(const std::string& file_name) = 0;
};
/// method to register a config_file_driver
extern CGV_API void register_config_file_driver(config_file_driver* cfd);
/// in case permanent registration is active, look for a registered object by name
extern named_ptr CGV_API find_object_by_name(const std::string& name);
/// in case permanent registration is active, look for a registered object by type name
extern base_ptr CGV_API find_object_by_type(const std::string& type_name);
/// interpret a config file
extern bool CGV_API process_config_file(const std::string& file_name);
/// interpret a gui file
extern bool CGV_API process_gui_file(const std::string& file_name);
//@}
/**@name loading of plugins*/
//@{
//! load a plugin or dll and return a handle to the plugin, or 0 if loading was not successful.
/*! During plugin loading the registration is always disabled in order to avoid deadlocks
that can arise when a registered object triggers loading of another dll.*/
extern CGV_API void* load_plugin(const std::string& file_name);
/// return a reference to the currently loaded plugin
extern CGV_API std::string& ref_plugin_name();
/// unload the plugin with the given handle
extern CGV_API bool unload_plugin(void* handle);
//@}
}
}
#include <cgv/config/lib_end.h>

View file

@ -0,0 +1,131 @@
#pragma once
#include "group.h"
#include "action.h"
#include <string>
#include "lib_begin.h"
namespace cgv {
namespace base {
/// different traversal policies
enum TraversePolicy {
TP_ALL, /// traverse all children
TP_ONLY_FOCUS, /// traverse only the focused child
TP_FIRST_FOCUS, /// first traverse focused and then the remaining children
TP_AUTO_FOCUS, /// like previous but change focus to the child, where traversal succeeded
TP_STOP_ON_SUCCESS = 8, /// this is an optional flag for traversals with methods that return a bool. If the returned bool is true, traversal stops if this flag is set
TP_STOP_ON_FAILURE = 16 /// this is an optional flag for traversals with methods that return a bool. If the returned bool is false, traversal stops if this flag is set
};
/// nodes should inherit from this policy class to allow selective tree traversals
class CGV_API traverse_policy
{
protected:
TraversePolicy policy;
bool active;
int focus;
public:
/// construct default traverse policy that visits everything
traverse_policy(int _policy = TP_ALL+TP_STOP_ON_SUCCESS, bool _active = true, int _focus = -1);
/// return the policy without the stop on success flag
int get_policy() const;
/// return whether to stop on success
bool stop_on_success() const;
/// return whether to stop on failure
bool stop_on_failure() const;
/// set a new policy, always add stop on success flag if needed
void set_policy(int _policy);
/// return the focused child or -1 if none is focused
int get_focused_child() const;
/// set the focused child
void set_focused_child(int _focused_child);
/// return whether the current node is active
bool get_active() const;
/// set the active flag of the current node
void set_active(bool _active);
};
/// try to grab the focus in the path of this node to the root of the tree
template <class X>
bool grab_focus(X* instance) {
node* n = dynamic_cast<node*>(instance);
if (!n)
return true;
base_ptr p = n->get_parent();
if (p.empty())
return true;
group_ptr g = p->get_group();
if (g.empty())
return true;
X* pinstance = p->get_interface<X>();
if (!pinstance)
return true;
for (unsigned int i=0; i<g->get_nr_children(); ++i) {
if (g->get_child(i)->get_interface<X>() == instance) {
pinstance->set_focused_child(i);
return grab_focus(pinstance);
}
}
// at this point we did not find the instance in the children of its parent
return false;
}
/// interface of a handler for traverse callbacks
class CGV_API traverse_callback_handler
{
public:
/// called before a node b is processed, return, whether to skip this node. If the node is skipped, the on_leave_node callback is still called
virtual bool on_enter_node(base_ptr b);
/// called when a node b is left, return whether to terminate traversal
virtual bool on_leave_node(base_ptr b);
/// called before the children of a group node g are processed, return whether these should be skipped. If children are skipped, the on_leave_children callback is still called.
virtual bool on_enter_children(group_ptr g);
/// called when the children of a group node g have been left, return whether to terminate traversal
virtual bool on_leave_children(group_ptr g);
/// called before the parent of a node n is processed, return whether this should be skipped. If the parent is skipped, the on_leave_parent callback is still called.
virtual bool on_enter_parent(node_ptr n);
/// called when the parent of a node n has been left, return whether to terminate traversal
virtual bool on_leave_parent(node_ptr n);
};
/// not yet implemented
enum TraverseStrategy
{
TS_DEPTH_FIRST,
TS_BREADTH_FIRST
};
/// class used to traverse a tree structure
class CGV_API traverser
{
protected:
action& a;
TraverseStrategy strategy;
std::string visit_order;
bool stop_if_not_implemented;
/// traverse a single object, template over a static traverse callback handler interface
template <typename TCH>
bool traverse_tmp_1(base_ptr dest, base_ptr src, bool& force_termination, TCH& tch);
/// helper method encapsulating common functionality
template <typename TCH>
bool traverse_tmp_2(base_ptr p, base_ptr dest, base_ptr src, traverse_policy* tp, bool& force_termination, TCH& tch);
public:
/// construct from reference on action and traversal order string
traverser(action& _a,
const std::string& _visit_order = "pnc",
TraverseStrategy _strategy = TS_DEPTH_FIRST,
bool _stop_if_not_implemented = false);
/// set a different visiting order of node, children and parent
traverser& set_visit_order(const std::string& _visit_order);
/// set a different traverse strategy
traverser& set_strategy(TraverseStrategy _strategy);
/// traverse a tree starting at given node according to set strategy, order and dest and previously coming from src and return whether traversal yielded success
bool traverse(base_ptr start, traverse_callback_handler* tch = 0);
};
}
}
#include <cgv/config/lib_end.h>

View file

@ -0,0 +1,9 @@
#pragma once
#if _MSC_VER > 1600
#define CPP11
#endif
//#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >=6)
//#define CPP11
//#endif

View file

@ -0,0 +1,42 @@
#ifdef _WIN32
# if _MSC_VER >= 1400
# pragma warning(disable:4275)
# pragma warning(disable:4231)
# pragma warning(disable:4251)
# endif
# if _MSC_VER >= 1500
# pragma warning (disable:4996)
# endif
# if defined(CGV_FORCE_STATIC_LIB) || defined(CGV_FORCE_STATIC)
# define CGV_API
# define CGV_IS_STATIC
# define CGV_TEMPLATE
# else
# if defined(CGV_EXPORTS) || defined(CGV_FORCE_EXPORT)
# define CGV_API __declspec(dllexport)
# define CGV_TEMPLATE
# else
# ifndef __INTEL_COMPILER
# define CGV_API __declspec(dllimport)
#ifdef _MSC_VER
# define CGV_TEMPLATE extern
#endif
# else
# define CGV_API
# define CGV_TEMPLATE
# endif
# endif
# endif
#ifdef _MSC_VER
# define FRIEND_MEMBER_API extern CGV_API
#else
# define FRIEND_MEMBER_API
#endif
#else
# define CGV_API
# define FRIEND_MEMBER_API
# define CGV_TEMPLATE
#endif
#undef CGV_EXPORTS
#undef CGV_FORCE_STATIC_LIB

View file

@ -0,0 +1,3 @@
#undef CGV_API
#undef CGV_TEMPLATE
#undef CGV_IS_STATIC

View file

@ -0,0 +1,98 @@
#pragma once
#include <iostream>
#include <fstream>
#include "io_reflection_handler.h"
#include "lib_begin.h"
namespace cgv {
namespace data {
/// different naming conventions for member names
enum NamingConvention { NC_NONE, NC_SHORT, NC_LONG };
}
}
namespace cgv {
namespace reflect {
extern CGV_API enum_reflection_traits<cgv::data::NamingConvention> get_reflection_traits(const cgv::data::NamingConvention&);
}
}
namespace cgv {
namespace data {
/** read from ascii file */
class CGV_API ascii_reflection_handler : public io_reflection_handler
{
public:
protected:
unsigned nr_idents;
NamingConvention naming_convention;
unsigned tab_size;
std::string extend_name(const std::string& name, bool assign = true);
public:
///
bool reflect_header();
///
ascii_reflection_handler(const std::string& _content, unsigned _ver, unsigned _tab = 3);
///
int reflect_group_begin(GroupKind group_kind, const std::string& group_name, void* group_ptr, cgv::reflect::abst_reflection_traits* rt, unsigned grp_size);
///
void reflect_group_end(GroupKind group_kind);
};
/** read from ascii file */
class CGV_API ascii_read_reflection_handler : public ascii_reflection_handler
{
protected:
std::ifstream file_is;
std::istream& is;
bool read_reflect_header(const std::string& _content, unsigned _ver);
public:
ascii_read_reflection_handler(const std::string& file_name, const std::string& _content, unsigned _ver, NamingConvention _nc = NC_SHORT, unsigned _tab = 3);
///
ascii_read_reflection_handler(std::istream& _is, const std::string& _content, unsigned _ver, NamingConvention _nc = NC_SHORT, unsigned _tab = 3);
/// this should return true
bool is_creative() const;
///
void close();
int reflect_group_begin(GroupKind group_kind, const std::string& group_name, void* group_ptr, cgv::reflect::abst_reflection_traits* rt, unsigned grp_size);
///
bool reflect_member_void(const std::string& member_name,
void* member_ptr, cgv::reflect::abst_reflection_traits* rt);
};
/** read from ascii file */
class CGV_API ascii_write_reflection_handler : public ascii_reflection_handler
{
protected:
std::ofstream file_os;
std::ostream& os;
public:
/// construct from file_name by opening file in ascii mode
ascii_write_reflection_handler(const std::string& file_name, const std::string& _content, unsigned _ver, NamingConvention _nc = NC_SHORT, unsigned _tab = 3);
/// construct from std::ostream
ascii_write_reflection_handler(std::ostream& _os, const std::string& _content, unsigned _ver, NamingConvention _nc = NC_SHORT, unsigned _tab = 3);
///
bool failed() const;
///
void close();
///
int reflect_group_begin(GroupKind group_kind, const std::string& group_name, void* group_ptr, cgv::reflect::abst_reflection_traits* rt, unsigned grp_size);
///
bool reflect_member_void(const std::string& member_name,
void* member_ptr, cgv::reflect::abst_reflection_traits* rt);
};
}
}
#include <cgv/config/lib_end.h>

View file

@ -0,0 +1,60 @@
#pragma once
#include <stdio.h>
#include "io_reflection_handler.h"
#include "lib_begin.h"
namespace cgv {
namespace data {
/** reflect to and from binary file */
class CGV_API binary_reflection_handler : public io_reflection_handler
{
protected:
FILE* fp;
public:
///
binary_reflection_handler(const std::string& _content, unsigned _ver);
///
bool reflect_header();
///
void close();
};
/** read from ascii file */
class CGV_API binary_read_reflection_handler : public binary_reflection_handler
{
protected:
bool read_reflect_header(const std::string& _content, unsigned _ver);
public:
binary_read_reflection_handler(const std::string& file_name, const std::string& _content, unsigned _ver);
///
binary_read_reflection_handler(FILE* _fp, const std::string& _content, unsigned _ver);
/// this should return true
bool is_creative() const;
///
bool reflect_member_void(const std::string& member_name,
void* member_ptr, cgv::reflect::abst_reflection_traits* rt);
};
/** read from ascii file */
class CGV_API binary_write_reflection_handler : public binary_reflection_handler
{
public:
/// construct from file_name by opening file in ascii mode
binary_write_reflection_handler(const std::string& file_name, const std::string& _content, unsigned _ver);
/// construct from std::ostream
binary_write_reflection_handler(FILE* _fp, const std::string& _content, unsigned _ver);
///
bool reflect_member_void(const std::string& member_name,
void* member_ptr, cgv::reflect::abst_reflection_traits* rt);
};
}
}
#include <cgv/config/lib_end.h>

View file

@ -0,0 +1,208 @@
#pragma once
#include <cgv/type/info/type_id.h>
#include <cgv/type/info/type_access.h>
#include "packing_info.h"
#include <string>
#include <vector>
#include "lib_begin.h"
using namespace cgv::type::info;
namespace cgv {
namespace data {
/** define standard formats, which should be used to avoid wrong
assignment of component names */
enum ComponentFormat {
CF_UNDEF, /// undefinded format with no component
CF_R, /// red channel of color format
CF_G, /// green channel of color format
CF_B, /// blue channel of color format
CF_A, /// alpha format
CF_L, /// color format with luminance component L
CF_I, /// color format with intensity component I
CF_LA, /// color format with luminance and alpha components: L and A
CF_IA, /// color format with intensity and alpha components: I and A
CF_RGB, /// color format with components R, G and B
CF_RGBA, /// color format with components R, G, B and A
CF_BGR, /// color format with components B, G and R
CF_BGRA, /// color format with components B, G, R and A
CF_D, /// depth component
CF_S, /// stencil component
CF_P2D, /// point format with components px and py
CF_P3D, /// point format with components px, py and pz
CF_P4D, /// point format with components px, py, pz and pw
CF_N2D, /// normal format with components nx and ny
CF_N3D, /// normal format with components nx, ny and nz
CF_T2D, /// texture coordinats format with components ts and tt
CF_T3D, /// texture coordinats format with components ts, tt and tr
CF_T4D, /// texture coordinats format with components ts, tt, tr and tq
CF_LAST /// this is always the last entry in the component formats and used for iteration
};
/** the component format inherits the information of a packing_info
and adds information on the component type, which components are
present in the data and in which order they appear */
class CGV_API component_format : public packing_info
{
protected:
/// store the type id of the component type
TypeId component_type;
/// store all component names in one string separated with 0-chars
std::string component_string;
/// store the position of each component in the component string
std::vector<unsigned short> component_positions;
/// extract components from component string
void extract_components();
/// store the last error that appeared during parsing of a description
static std::string last_error;
public:
/// construct from description string, see set_component_format for docu
explicit component_format(const std::string& description);
/**
set component format from description string, which has the following syntax.
If a parse error arises, return false and set the static last_error member, which
can be queried with get_last_error():
\verbatim
component_format <- [type] [attributes] '[' component [',' component]* ']'
component <- component_name [attributes]
attributes <- [':' bit_depth]['|' alignment]
type <- "undef" | "bool" | "int8" | "int16" | "int32" | "uint64" |
"uint8" | "uint16" | "uint32" | "uint64" |
"flt16" | "flt32" | "flt64" | "string"
component_name : string ... name of component, i.e. "R", "Cb", "px", ...
bit_depth : unsigned int ... number of bits used to represent a component
alignment : unsigned int ... number of bits to which a component is aligned
\endverbatim
Some examples of valid component format description strings:
- \c "uint8:3|4[R,G,B,A]" ... four components represented as unsigned integers
with no more than 8 bits. Actually, each component is
stored with 3 bits and aligned to a bit index which
is a multiple of 4
- \c "uint8[R:5,G:6,B:5]" ... three components packed into 16 bits with 5 bits for R,
6 for G and 5 for B.
- \c "flt32[px,py]" ... two components of 32 bit floats
- \c "[D]" ... one depth component without specified type, which defaults
to "undef" and implies that the default depth format should
be used.
*/
bool set_component_format(const std::string& description);
/// comma separated list of component descriptors, for example "R,G,B"
void set_components(const std::string& _components);
/// returns an error string after parsing of description string has failed
static const std::string& get_last_error();
/** construct component format from component type, comma or colon
separated list of component names, component alignment and bit
depths for packed formats*/
component_format(TypeId _component_type = TI_UNDEF,
const std::string& _component_name_list = "",
unsigned int align = 1,
unsigned int d0 = 0, unsigned int d1 = 0,
unsigned int d2 = 0, unsigned int d3 = 0);
/// construct component format from component type, standard component format, component alignment and bit depths for packed formats
component_format(TypeId _component_type,
ComponentFormat cf,
unsigned int align = 1,
unsigned int d0 = 0, unsigned int d1 = 0,
unsigned int d2 = 0, unsigned int d3 = 0);
/// define stream out operator
friend FRIEND_MEMBER_API std::ostream& operator << (std::ostream& os, const component_format& cf);
/// constant access to the i-th component stored at the given location
template <typename T>
T get(int ci, const void* ptr) const {
if (is_packing()) {
if (get_component_type() <= TI_INT64) {
int i = packing_info::get_signed(ci, ptr);
return type_access<T>::get(&i, get_component_type());
}
else {
unsigned int i = packing_info::get_unsigned(ci, ptr);
return type_access<T>::get(&i, get_component_type());
}
}
else
return type_access<T>::get(static_cast<const unsigned char*>(ptr)+ci*align(get_type_size(get_component_type()),get_component_alignment()), get_component_type());
}
/// write access to the i-th component, return whether write was successful
template <typename T>
bool set(int ci, void* ptr, const T& v) const {
if (is_packing()) {
if (get_component_type() <= TI_INT64) {
int i = 0;
return type_access<T>::set(&i, get_component_type(), v) && packing_info::set_signed(ci, ptr, i);
}
else {
unsigned int i = 0;
return type_access<T>::set(&i, get_component_type(), v) && packing_info::set_unsigned(ci, ptr, i);
}
}
else
return type_access<T>::set(static_cast<unsigned char*>(ptr)+ci*align(get_type_size(get_component_type()),get_component_alignment()), get_component_type(), v);
}
/// return whether the component format is defined
bool empty() const;
/// clear the component format
void clear();
/// return the packing info by simple conversion of the this pointer
const packing_info& get_packing_info() const;
/// set packing info by simply assigning to a converted this pointer
void set_packing_info(const packing_info& pi);
/// return the number of components
unsigned int get_nr_components() const;
/// return the index of a component given by name or -1 if not found
unsigned int get_component_index(const std::string& name) const;
/// return the name of the component with index i
std::string get_component_name(unsigned int i) const;
/// return whether the component format is one of the standard formats
ComponentFormat get_standard_component_format() const;
/// set component names from a comma or colon separated list of names
void set_component_names(const std::string& _component_name_list);
/// set the component names from a standard component format
void set_component_format(ComponentFormat _cf);
/// return the component type
TypeId get_component_type() const;
/// set the component type
void set_component_type(TypeId _type_id);
/// return the size of one entry of components in bytes
unsigned int get_entry_size() const;
/// comparison between component formats
bool operator == (const component_format& cf) const;
/// comparison between component formats
bool operator != (const component_format& cf) const;
};
/** stream out operator writes the component format in the syntax of description strings
as defined in the docu of set_component_format(). */
extern CGV_API std::ostream& operator << (std::ostream& os, const component_format& cf);
/// default function to check whether fmt1 is a better match to fmt than fmt2
extern CGV_API bool fmt1_compares_better(const component_format& fmt,
const component_format& fmt1,
const component_format& fmt2);
/** find the best matching format in a list of formats described by strings
and return index of best match */
extern CGV_API unsigned int find_best_match(
const component_format& fmt,
const char** format_descriptions,
const component_format* fmt0 = 0,
bool (*fmt1_better_match)(
const component_format& fmt,
const component_format& fmt1,
const component_format& fmt2) = fmt1_compares_better);
}
}
#include <cgv/config/lib_end.h>

View file

@ -0,0 +1,194 @@
#pragma once
#include "component_format.h"
#include "lib_begin.h"
using namespace cgv::type::info;
namespace cgv {
namespace data {
/** A data_format describes a multidimensional data block of data entries.
It inherits the information stored in component info which describes
which components each data entry has. The data_format adds information
about the dimensionality and the alignment and resolution in each
dimension. */
class CGV_API data_format : public component_format
{
protected:
struct dimension_info
{
unsigned int resolution;
unsigned int alignment;
unsigned int layout_dimension;
dimension_info(unsigned int n = 0, unsigned int a = 1, unsigned int ld = 0)
: resolution(n), alignment(a), layout_dimension(ld) {}
};
/// store for each dimension resolution and alignment in a dimension_info struct
std::vector<dimension_info> dimensions;
public:
/// construct an undefined data format
data_format();
/// construct from description string, see set_data_format for docu
explicit data_format(const std::string& description);
/**
Set data format from description string, which adds information to the description string
of the component format and has the following syntax. For the definition of the token
\c component_format in the syntax definition refer to the docu of
component_format::set_component_format(). If a parse error arises, return false and set
the static last_error member, which can be queried with get_last_error().
Syntax definition:
\verbatim
data_format <- component_format['|' alignment_in_bytes] '(' dimension_info (',' dimension_info)* ')'
dimension_info <- resolution [':' layout_dimension]['|' alignment_in_bytes]
- resolution : unsigned int ... number of entries in specified dimension
- layout_dimension : unsigned int ... index of dimension in memory layout, which defaults
to the specified dimension
- alignment_in_bytes : unsigned int ... alignment in the memory layout for entries with index zero
in the specified dimension
\endverbatim
In the standard memory layout of for example an image, the entries are arranged line by line,
i.e. first the entries of the first line are stored from left to right, followed by the entries
of the second line and so on. To change this order of the layout, one can specify for each
dimension in the data format a layout dimension which defaults to the dimension index, i.e.
if the layout dimensions of all dimensions correspond to the dimension index, the memory layout
is starting with the 0-th dimension. To store an image in a columns first memory layout, the
layout dimensions would be 1 and 0 for dimensions 0 and 1.
Some examples of valid data format description strings:
- \c "uint8[R,G,B](127|8,256)" ... 127x256 RGB-image, where each line is aligned to multiples of 8
- \c "uint8[R,G,B](127:1,256:0)" ... 127x256 RGB-image stored in column major memory layout
- \c "uint16[L:12,A:12]|4(32,32,32)" ... 32x32x32 12-Bit Luminance Alpha Volume, where each
entry is aligned to 4 bytes
*/
bool set_data_format(const std::string& description);
/// construct a 1d data format from width and the information needed to construct a component info
data_format(unsigned int _width,
TypeId _component_type,
const std::string& _component_name_list,
unsigned int align = 1,
unsigned int d0 = 0, unsigned int d1 = 0,
unsigned int d2 = 0, unsigned int d3 = 0);
/// construct a 1d data format from width and the information needed to construct a component info
data_format(unsigned int _width,
TypeId _component_type,
ComponentFormat _cf,
unsigned int align = 1,
unsigned int d0 = 0, unsigned int d1 = 0,
unsigned int d2 = 0, unsigned int d3 = 0);
/// construct a 2d data format from width and height
data_format(unsigned int _width, unsigned int _height,
TypeId _component_type,
const std::string& _component_name_list,
unsigned int align = 1,
unsigned int d0 = 0, unsigned int d1 = 0,
unsigned int d2 = 0, unsigned int d3 = 0);
/// construct a 2d data format from width and height
data_format(unsigned int _width, unsigned int _height,
TypeId _component_type,
ComponentFormat _cf,
unsigned int align = 1,
unsigned int d0 = 0, unsigned int d1 = 0,
unsigned int d2 = 0, unsigned int d3 = 0);
/// construct a 3d data format from width, height and depth
data_format(unsigned int _width, unsigned int _height, unsigned int _depth,
TypeId _component_type,
const std::string& _component_name_list,
unsigned int align = 1,
unsigned int d0 = 0, unsigned int d1 = 0,
unsigned int d2 = 0, unsigned int d3 = 0);
/// construct a 3d data format from width, height and depth
data_format(unsigned int _width, unsigned int _height, unsigned int _depth,
TypeId _component_type,
ComponentFormat _cf,
unsigned int align = 1,
unsigned int d0 = 0, unsigned int d1 = 0,
unsigned int d2 = 0, unsigned int d3 = 0);
/// construct a 4d data format from width, height, depth and count
data_format(unsigned int _width, unsigned int _height,
unsigned int _depth, unsigned int _count,
TypeId _component_type,
const std::string& _component_name_list,
unsigned int align = 1,
unsigned int d0 = 0, unsigned int d1 = 0,
unsigned int d2 = 0, unsigned int d3 = 0);
/// construct a 4d data format from width, height, depth and count
data_format(unsigned int _width, unsigned int _height,
unsigned int _depth, unsigned int _count,
TypeId _component_type,
ComponentFormat _cf,
unsigned int align = 1,
unsigned int d0 = 0, unsigned int d1 = 0,
unsigned int d2 = 0, unsigned int d3 = 0);
/// define stream out operator
friend FRIEND_MEMBER_API std::ostream& operator << (std::ostream& os, const data_format& df);
/// set the dimensions to the given values
void set_dimensions(unsigned _d0, unsigned _d1 = -1, unsigned _d2 = -1, unsigned _d3 = -1);
/// return the number of dimensions of the data set
unsigned int get_nr_dimensions() const;
/// set the number of dimensions of the data set
void set_nr_dimensions(unsigned int _d);
/// return the resolution in the i-th dimension, or 0 if not defined
unsigned int get_resolution(unsigned int i) const;
/// return the resolution in the first dimension, or 1 if not defined
unsigned int get_width() const;
/// return the resolution in the second dimension, or 1 if not defined
unsigned int get_height() const;
/// return the resolution in the third dimension, or 1 if not defined
unsigned int get_depth() const;
/// return the resolution in the highest dimension, or 1 if not defined
unsigned int get_nr_time_steps() const;
/// return the total number of data entries
unsigned int get_size() const;
/// return the total number of bytes necessary to store the data
unsigned int get_nr_bytes() const;
/// set the resolution in the i-th dimension, add dimensions if necessary
void set_resolution(unsigned int i, unsigned int resolution);
/// set the resolution in the first dimension, add dimensions if necessary
void set_width(unsigned int _width);
/// set the resolution in the second dimension, add dimensions if necessary
void set_height(unsigned int _height);
/// set the resolution in the third dimension, add dimensions if necessary
void set_depth(unsigned int _depth);
/// set the resolution in the last dimension, add dimensions if necessary
void set_nr_time_steps(unsigned int _nr_time_steps);
/// return the alignment of entries
unsigned int get_entry_alignment() const;
/** return the alignment of a given dimension, where the alignment of the
last dimension is always 1 and cannot be changed. This method also returns 1
if i is out of the range of valid dimensions. */
unsigned int get_alignment(unsigned int i) const;
/// set the alignment of entries
void set_entry_alignment(unsigned int _a);
/** set the alignment of a given dimension, add dimensions if necessary. The
alignment of the last dimension is always 1 and cannot be set.*/
void set_alignment(unsigned int i, unsigned int _a);
/// return the layout dimension of a given dimension
unsigned int get_layout_dimension(unsigned int dim) const;
/// set the layout dimension of a given dimension, add dimensions if necessary
void get_layout_dimension(unsigned int dim, unsigned int layout_dim);
/// return the component_format info by simple conversion of the this pointer
const component_format& get_component_format() const;
/// set component_format by simply assigning to a converted this pointer
void set_component_format(const component_format& cf);
/// comparison between component formats
bool operator == (const data_format& df) const;
/// comparison between component formats
bool operator != (const data_format& df) const;
};
/** stream out operator writes the data format in the syntax of description strings
as defined in the docu of set_data_format(). */
extern CGV_API std::ostream& operator << (std::ostream& os, const data_format& df);
}
}
#include <cgv/config/lib_end.h>

View file

@ -0,0 +1,228 @@
#pragma once
#include <cgv/type/info/type_ptr.h>
#include <cgv/type/func/transfer_const.h>
#include <cgv/data/data_format.h>
#include "lib_begin.h"
namespace cgv {
namespace data {
/** base class of both implementations of the data view managing the
component format, the dimension of the view and the step sizes */
class CGV_API data_view_base
{
protected:
const data_format* format;
/// whether to own the data format
bool owns_format;
unsigned int dim;
unsigned int step_sizes[4];
/// constructor used to construct sub views onto the data view
data_view_base(const data_format* _format, unsigned int _dim,
const unsigned int* _step_sizes);
public:
/** construct the base of a data view from the given format,
such that the step sizes and dimension are set to view
the complete data set defined in the format. */
data_view_base(const data_format* _format = 0);
/// delete format if it is owned
~data_view_base();
/// whether to manage the data format pointer
void manage_format(bool enable = true);
/// return the component format
const data_format* get_format() const;
/// set a new data format
void set_format(const data_format* _format);
/// return the dimension of the data view, which is less or equal to the dimension of the data format
unsigned int get_dim() const;
/// return the step size in bytes in the i-th dimension
unsigned int get_step_size(unsigned int dim) const;
};
/** template class implementing the part of the view that depends on whether
the pointer is const or not and manages the data pointer itself. */
template <class D, typename T = unsigned char>
class CGV_API data_view_impl : public data_view_base
{
protected:
/// data pointer of type unsigned char or const unsigned char
T* data_ptr;
/// constructor used to construct sub views onto the data view
data_view_impl(const data_format* _format, T* _data_ptr,
unsigned int _dim, const unsigned int* _step_sizes);
public:
/// construct a data view from the given format, viewing the complete data set
data_view_impl(const data_format* _format = 0,
typename cgv::type::func::transfer_const<T,void>::type* _data_ptr = 0);
/// return whether the data pointer is a null pointer
bool empty() const;
/// return a pointer to the data
template <typename S>
typename cgv::type::func::transfer_const<T,S>::type* get_ptr() const {
return (typename cgv::type::func::transfer_const<T,S>::type*)(data_ptr);
}
/// return a pointer to i-th data entry
const T* get_ptr(int i) const {
return data_ptr+i*step_sizes[0];
}
/// return a pointer to (i,j)-th data entry
const T* get_ptr(int i, int j) const {
return data_ptr+i*step_sizes[0]+j*step_sizes[1];
}
/// return a pointer to (i,j,k)-th data entry
const T* get_ptr(int i, int j, int k) const {
return data_ptr+i*step_sizes[0]+j*step_sizes[1]+k*step_sizes[2];
}
/// return a pointer to (i,j,k,l)-th data entry
const T* get_ptr(int i, int j, int k, int l) const {
return data_ptr+i*step_sizes[0]+j*step_sizes[1]+k*step_sizes[2]+l*step_sizes[3];
}
/// constant access to the ci-th component
template <typename S>
S get(int ci) const {
return format->get<S>(ci, data_ptr);
}
/// constant access to the ci-th component of i-th data entry
template <typename S> S get(int ci, int i) const {
return format->get<S>(ci, get_ptr(i));
}
/// constant access to the ci-th component of (i,j)-th data entry
template <typename S> S get(int ci, int i, int j) const {
return format->get<S>(ci, get_ptr(i,j));
}
/// constant access to the ci-th component of (i,j,k)-th data entry
template <typename S> S get(int ci, int i, int j, int k) const {
return format->get<S>(ci, get_ptr(i,j,k));
}
/// constant access to the ci-th component of (i,j,k,l)-th data entry
template <typename S> S get(int ci, int i, int j, int k, int l) const {
return format->get<S>(ci, get_ptr(i,j,k,l));
}
/// access to i-th data entry
D operator () (unsigned int i) const;
/// access to entry at (i,j)
D operator () (unsigned int i, unsigned int j) const;
/// access to entry at (i,j,k)
D operator () (unsigned int i, unsigned int j, unsigned int k) const;
/// access to entry at (i,j,k,l)
D operator () (unsigned int i, unsigned int j, unsigned int k, unsigned int l) const;
/** permute the order of the indices, where the permutation argument "kji" implies that after
the permutation the operator (i,j,k) returns the same as the operator (k,j,i) before the
call to permute. The permutation string must have at least two entries. If it has n entries
it must contain each of the first n letters of "ijkl" exactly once, i.e. "ik" would be invalid,
whereas "ikj" is a valid permutation. */
D permute(const std::string& permutation) const;
/// transpose is equivalent to permute("ji")
D transpose() const { return permute("ji"); }
/// return a pointer that points to the n-th next location if index i is increase by n
template <typename S>
typename cgv::type::func::transfer_const<T,S>::type*
step_i(S* ptr, int n=1) const { return static_cast<typename cgv::type::func::transfer_const<T,S>::type*>(static_cast<T*>(ptr)+n*step_sizes[0]); }
/// return a pointer that points to the n-th next location if index j is increase by n
template <typename S>
typename cgv::type::func::transfer_const<T,S>::type*
step_j(S* ptr, int n=1) const { return static_cast<typename cgv::type::func::transfer_const<T,S>::type*>(static_cast<T*>(ptr)+n*step_sizes[1]); }
/// return a pointer that points to the n-th next location if index k is increase by n
template <typename S>
typename cgv::type::func::transfer_const<T,S>::type*
step_k(S* ptr, int n=1) const { return static_cast<typename cgv::type::func::transfer_const<T,S>::type*>(static_cast<T*>(ptr)+n*step_sizes[2]); }
/// return a pointer that points to the n-th next location if index l is increase by n
template <typename S>
typename cgv::type::func::transfer_const<T,S>::type*
step_l(S* ptr, int n=1) const { return static_cast<typename cgv::type::func::transfer_const<T,S>::type*>(static_cast<T*>(ptr)+step_sizes[3]); }
};
class CGV_API const_data_view;
/** the data view gives access to a data array of one, two, three or four
dimensions. Each data entry can consist of several components as defined
in the referenced component format. It allows to permute the dimensions,
construct views of lower dimension with the ()-operators defined in the
data_view_impl and to access the data components with the get- and
set-method of data_view_impl.
It keeps a flag that tells whether the data pointer belongs to the
data view and therefore needs to be deleted on destruction.
*/
class CGV_API data_view : public data_view_impl<data_view, unsigned char>
{
protected:
/// declare base as friend
friend class data_view_impl<data_view, unsigned char>;
friend class const_data_view;
/// a flag telling whether the data ptr is owned by the view
bool owns_ptr;
/// use base class for construction and don't manage data pointer
data_view(const data_format* _format, unsigned char* _data_ptr,
unsigned int _dim, const unsigned int* _step_sizes);
public:
/// construct an empty data view without format and with empty data pointer*/
data_view();
/// destruct view and delete data pointer if it is owned by the view
~data_view();
/** construct a data view from the given format. Allocate a new data
pointer with the new [] operator of type (unsigned char) and own
the pointer. The data_view will view the complete data set as defined
in the format. */
data_view(const data_format* _format);
/** construct a data view from the given format, viewing the complete
data set. The passed pointer will not be owned by the view. */
data_view(const data_format* _format, void* _data_ptr);
/** construct a data view from the given format, viewing the complete
data set. The passed pointer will be owned by the view if the
manage_ptr flag is true. In this case the pointer is deleted on
destruction with the delete [] operator of type (unsigned char*). */
data_view(const data_format* _format, unsigned char* _data_ptr, bool manage_ptr);
/** the assignment operator takes over the data format and data pointers
in case they are managed by the source data view */
data_view& operator = (const data_view& dv);
/** set a different data pointer that will be deleted with the
delete [] operator of type (unsigned char*) on destruction
if the manage_ptr flag is true */
void set_ptr(unsigned char* ptr, bool manage_ptr);
/** set a different data pointer that is not owned by the data view
and will not be deleted on destruction. */
void set_ptr(void* ptr);
/// write access to the i-th component, return whether write was successful
template <typename T>
bool set(int ci, const T& v) {
return format->set(ci, data_ptr, v);
}
/// reflect 2D data view at horizontal axis
void reflect_horizontally();
};
/** The const_data_view has the functionality of the data_view but
uses a const pointer and therefore does not allow to manage the
pointer nor to set the data.
*/
class CGV_API const_data_view : public data_view_impl<const_data_view, const unsigned char>
{
protected:
/// declare base as friend
friend class data_view_impl<const_data_view, const unsigned char>;
/// use base class for construction
const_data_view(const data_format* _format, const unsigned char* _data_ptr,
unsigned int _dim, const unsigned int* _step_sizes);
public:
/// construct an empty data view without format and with empty data pointer*/
const_data_view();
/// copy construct from a non const data view
const_data_view(const data_view& dv);
/** construct a data view from the given format, viewing the complete
data set pointed to by the passed data pointer */
const_data_view(const data_format* _format, const void* _data_ptr);
/// assignment of const_data_view never gains ownership of format or data
const_data_view& operator = (const const_data_view& dv);
/// set a different data pointer
void set_ptr(const void* ptr);
};
}
}
#include <cgv/config/lib_end.h>

View file

@ -0,0 +1,169 @@
#pragma once
#include <vector>
namespace cgv {
namespace data {
/** IndexHeap is a heap that allows changing of the elements */
template <typename T>
class dynamic_priority_queue
{
public:
typedef T element_type;
protected:
/// store per element, whether it is empty and a link to the next empty element or to the heap location
struct extended_element
{
element_type element;
bool is_empty : 1;
unsigned int link : 31;
};
/// container for elements
std::vector<extended_element> elements;
/// store index of last empty element or -1 if there is non
int last_empty_element;
/// store indices to the elements on the heap
std::vector<unsigned int> heap;
/// check if a position is outside of range
bool valid(unsigned int hp) const { return hp < heap.size(); }
/// make sure that the link for hp is ok
void updateLink(unsigned int hp) { elements[heap[hp]].link = hp; }
/// check if hp1 is less than hp2, if true, exchange elements
bool isBetter(unsigned int hp1, unsigned int hp2) const {
return elements[heap[hp1]].element<elements[heap[hp2]].element;
}
/// check if hp1 is less than hp2, if true, exchange elements
bool exchangeIfBetter(unsigned int hp1, unsigned int hp2)
{
if (isBetter(hp1,hp2)) {
std::swap(heap[hp1], heap[hp2]);
updateLink(hp1);
updateLink(hp2);
return true;
}
return false;
}
///
void heapify(unsigned int hp) { if (!positionUpward(hp)) positionDownward(hp); }
/// move one element to another position, that should be empty
void move(unsigned int hp1, unsigned int hp2)
{
heap[hp2] = heap[hp1];
updateLink(hp2);
}
/// remove an element on a certain heap pos
void removeHeap(unsigned int hp)
{
if (hp != heap.size()-1) {
move((unsigned int)heap.size()-1,hp);
heap.pop_back();
heapify(hp);
}
else
heap.pop_back();
}
/// move an element downward to the correct position
void positionDownward(unsigned int& hp)
{
unsigned int child;
while (valid(child = 2*hp+1)) {
unsigned int tmp = child+1;
if (valid(tmp) && isBetter(tmp,child)) child = tmp;
if (!exchangeIfBetter(child, hp)) break;
hp = child;
}
}
/// move an element upward to the correct position
bool positionUpward(unsigned int& hp)
{
bool changed = false;
while (hp != 0) {
unsigned int pa = (hp-1)/2;
if (!exchangeIfBetter(hp, pa)) break;
hp = pa;
changed = true;
}
return changed;
}
public:
/// empty construction
dynamic_priority_queue() : last_empty_element(-1) {}
/// remove all elements
void clear() { elements.clear(); heap.clear(); last_empty_element = -1; }
/// check if heap is empty
bool empty() const { return heap.size() == 0; }
/// return the number of elements in the heap
size_t size() const { return heap.size(); }
/// return the number of elements in the heap
size_t size_of_element_container() const { return elements.size(); }
/**@name queue interface */
//@{
/// return the top element
unsigned int top() const { return heap[0]; }
/// remove top element
void pop() { remove(top()); }
/// extract top element
int extract()
{
unsigned int tmp = top();
pop();
return tmp;
}
//@}
/**@name dynamic element access*/
//@{
///
bool is_empty(unsigned int idx) const { return elements[idx].is_empty; }
///
const element_type& operator [] (unsigned int idx) const { return elements[idx].element; }
element_type& operator [] (unsigned int idx) { return elements[idx].element; }
/// insert the given element and return its index in the element container
unsigned int insert(const element_type& e)
{
unsigned int idx;
if (last_empty_element != -1) {
idx = last_empty_element;
if (elements[idx].link == idx)
last_empty_element = -1;
else
last_empty_element = elements[idx].link;
}
else {
idx = (unsigned int) elements.size();
elements.resize(idx+1);
}
elements[idx].element = e;
elements[idx].is_empty = false;
unsigned int hp = (unsigned int) heap.size();
heap.push_back(idx);
updateLink(hp);
positionUpward(hp);
return idx;
}
/// update after a change to the predicate
void update(unsigned int idx)
{
if (!is_empty(idx))
heapify(elements[idx].link);
}
/// remove element at location idx
void remove(unsigned int idx)
{
if (is_empty(idx))
return;
removeHeap(elements[idx].link);
elements[idx].is_empty = true;
if (last_empty_element == -1)
elements[idx].link = idx;
else
elements[idx].link = last_empty_element;
last_empty_element = idx;
}
};
}
}

View file

@ -0,0 +1,43 @@
#pragma once
#include "data_view.h"
#include "lib_begin.h"
namespace cgv {
namespace data {
class CGV_API image_view
{
public:
data_format df;
data_view dv;
void* ref_void(int i, int j);
const void* get_void(int i, int j) const;
public:
image_view();
int get_width() const { return df.get_width(); }
int get_height() const { return df.get_height(); }
data_view& ref_data_view() { return dv; }
void create(const std::string& fmt_dcr, int w=-1, int h=-1);
void clear(double v);
/*
bool read(const std::string& fn);
bool write(const std::string& fn) const;
*/
template <typename T>
T& ref(int i, int j) { return *((T*)ref_void(i,j)); }
template <typename T>
const T& get(int i, int j) const { return *((const T*)get_void(i,j)); }
template <typename T>
T* ptr(int i, int j) { return (T*)ref_void(i,j); }
void copy_rectangle(const image_view& src, int X = 0, int Y = 0, int x = 0, int y = 0, int w = -1, int h = -1);
void sub_sample();
};
}
}
#include <cgv/config/lib_end.h>

View file

@ -0,0 +1,45 @@
#pragma once
#include <fstream>
#include <cgv/reflect/reflection_handler.h>
#include <cgv/reflect/reflect_enum.h>
#include "lib_begin.h"
namespace cgv {
namespace data {
/// different error codes
enum IOReflectionError { RE_NO_ERROR, RE_FILE_OPEN_ERROR, RE_FILE_READ_ERROR, RE_FILE_WRITE_ERROR, RE_CONTENT_MISMATCH, RE_VERSION_MISMATCH };
extern CGV_API cgv::reflect::enum_reflection_traits<IOReflectionError> get_reflection_traits(const IOReflectionError&);
/** common base for all io reflection handlers */
class CGV_API io_reflection_handler : public cgv::reflect::reflection_handler
{
public:
protected:
unsigned version;
std::string file_content;
bool in_header;
IOReflectionError last_error;
public:
///
io_reflection_handler(const std::string& _content, unsigned _ver);
///
bool failed() const;
///
IOReflectionError get_error_code() const;
///
static std::string get_error_message(IOReflectionError ae);
///
bool reflect_method_void(const std::string& method_name, cgv::reflect::method_interface* mi_ptr,
cgv::reflect::abst_reflection_traits* return_traits, const std::vector<cgv::reflect::abst_reflection_traits*>& param_value_traits);
};
}
}
#include <cgv/config/lib_end.h>

View file

@ -0,0 +1,8 @@
#if defined(CGV_DATA_FORCE_STATIC)
# define CGV_FORCE_STATIC_LIB
#endif
#ifdef CGV_DATA_EXPORTS
# define CGV_EXPORTS
#endif
#include <cgv/config/lib_begin.h>

View file

@ -0,0 +1,73 @@
#pragma once
#include <cgv/data/lib_begin.h>
namespace cgv {
namespace data {
/** the packing_info class stores information about packed integers
structures. It is typically used to define packed component formats.
The stored information includes, whether packing is used,
the alignment of the components and bit depths of up to 4 components.
The aligment is an integer defining a multiple to which the components
are aligned. If the alignment is 1, the components are packed densely.
If it is for example 8, the components are stored at starting at
locations that are multiples of 8. For example if the components have
bit depth 6 and the alignment is 8, then the first component is stored
starting with the first bit, the second component starting with the 8th
bit and so on. In case no packing is used the alignment is measured in
bytes. The bit depths and alignment are stored as unsigned integers
with 6 bits, i.e. the maximum value is 63.
*/
class CGV_API packing_info
{
protected:
bool is_packed : 1;
unsigned int bd0 : 6;
unsigned int bd1 : 6;
unsigned int bd2 : 6;
unsigned int bd3 : 6;
unsigned int ca : 6;
///
bool prepare_bit_operation(unsigned int ci, void* ptr, unsigned int &off, unsigned int &bd, unsigned int* &iptr) const;
bool prepare_bit_operation(unsigned int ci, const void* ptr, unsigned int &off, unsigned int &bd, const unsigned int* &iptr) const;
unsigned int get_bit_offset(unsigned int ci) const;
public:
/** construct packing information from alignment and bit depths. If no bit depths are given, the components are not
packed and the alignment is in bytes. If one or more depths are specified, the alignment is in bits. If exactly
one depth is given, all component bit depths are set to this bit depth */
packing_info(unsigned int align = 1, unsigned int d0 = 0, unsigned int d1 = 0, unsigned int d2 = 0, unsigned int d3 = 0);
/// clear packing info information
void clear();
/// return the bit depth of the ci-th component
unsigned int get_bit_depth(unsigned int ci) const;
/// set the bit depth of the ci-th component
void set_bit_depth(unsigned int ci, unsigned int depth);
/// return whether packing is enabled
bool is_packing() const;
/// set the packing flag
void set_packing(bool enable = true);
/// return the component alignment in bits in the packed case and in bytes in the unpacked case
unsigned int get_component_alignment() const;
/// set the component alignment in bits in the packed case and in bytes in the unpacked case
void set_component_alignment(unsigned int a);
/// return the next integer larger or equal to v which is dividable by a
static unsigned int align(unsigned int v, unsigned int a);
/// return the ci-th component of the data entry pointed to by the given pointer of a signed packed component
int get_signed(unsigned int ci, const void* ptr) const;
/// return the ci-th component of the data entry pointed to by the given pointer of an unsigned packed component
unsigned int get_unsigned(unsigned int ci, const void* ptr) const;
/// set the ci-th component of the data entry pointed to by the given pointer of a signed packed component
bool set_signed(unsigned int ci, void* ptr, int v) const;
/// set the ci-th component of the data entry pointed to by the given pointer of an unsigned packed component
bool set_unsigned(unsigned int ci, void* ptr, unsigned int v) const;
/// equal comparison
bool operator == (const packing_info& pi) const;
/// unequal comparison
bool operator != (const packing_info& pi) const;
};
}
}
#include <cgv/config/lib_end.h>

View file

@ -0,0 +1,109 @@
#pragma once
#include <cgv/defines/assert.h>
#include <cgv/type/cond/is_base_of.h>
#include <cgv/type/cond/has_virtual_destructor.h>
namespace cgv {
/// namespace for data management components
namespace data {
template <typename T>
class ref_arr
{
private:
/// struct to store the array pointer with a count
struct counter_type
{
counter_type(T* a, int c) : arr(a), count(c) {}
T* arr;
int count;
};
/// store pointer to counter struct
counter_type* counter;
/// store pointer to array
T* arr;
/// decrement the count, delete if it is 0
void release()
{
if (counter) {
if (--counter->count == 0) {
delete [] counter->arr;
delete counter;
}
counter = 0;
}
arr = 0;
}
public:
/// construct reference counted pointer
explicit ref_arr(T* a = 0, counter_type* c = 0) : counter(c), arr(a) {
if (!c && a)
counter = new counter_type(a, 1);
}
/// copy construct from same pointer type and increment count
ref_arr(const ref_arr<T>& ra) : counter(ra.counter), arr(ra.arr)
{
if (counter)
++counter->count;
}
/// destruct reference counted pointer
~ref_arr() {
release();
}
/// assignment to pointer of same type
ref_arr<T>& operator = (const ref_arr<T>& ra) {
if (this == &ra)
return *this;
release();
new (this) ref_arr<T>(ra);
return *this;
}
/// return array pointer
T* ptr() const {
return arr;
}
/// access to element
T& operator*() const {
return *arr;
}
/// access to element pointer
T* operator->() const {
return arr;
}
/// access to i-th element
T& operator [] (int i) {
return arr[i];
}
/// return an array pointer pointing to the i-th element
ref_arr<T> operator () (int i) const {
return ref_arr<T>(arr+i,counter);
}
/// compare by pointer
bool operator == (const ref_arr<T>& ra) const {
return arr == ra.arr;
}
/// return current count
int get_count() const {
return counter ? counter->count : 0;
}
/// check if this is the only reference
bool unique() const {
return get_count() <= 1;
}
/// check if pointer is not yet set
bool empty() const {
return get_count() == 0;
}
/// conversion to bool results in false if the stored pointer is a null pointer
operator bool () const {
return !empty();
}
/// clear the array pointer
void clear() {
release();
}
};
}
}

View file

@ -0,0 +1,27 @@
#pragma once
namespace cgv {
namespace data {
class ref_ptr_tag;
/** if you derive your class from this class, a ref_ptr will do reference counting in the inhereted
ref_count member. */
class ref_counted
{
private:
/// keep a mutable reference count to allow ref counted points to const instances
mutable int ref_count;
protected:
friend class ref_ptr_tag;
/// constructor initializes the count to 0
inline ref_counted() : ref_count(0) {}
/// write access is also const to allow ref counted pointers to const instances
inline void set_ref_count(int c) const { ref_count = c; }
public:
/// read access to current count
inline int get_ref_count() const { return ref_count; }
};
}
}

View file

@ -0,0 +1,245 @@
#pragma once
#include "ref_counted.h"
#include <cgv/defines/assert.h>
#include <cgv/type/cond/is_base_of.h>
#include <cgv/type/cond/has_virtual_destructor.h>
#include <assert.h>
#include "lib_begin.h"
namespace cgv {
/// namespace for data management components
namespace data {
// extern CGV_API bool validate_delete(const void* ptr);
template <class T, bool is_ref_counted>
class ref_ptr;
/// struct used to make ref pointers to ref_counted friends of ref_counted
class ref_ptr_tag
{
protected:
/// increment the count of a ref counted object
void inc_ref_count(const ref_counted* ptr) const
{
ptr->set_ref_count(ptr->get_ref_count()+1);
}
/// decrement the count of a ref counted object and return whether to delete the object
bool dec_ref_count(const ref_counted* ptr) const
{
int count = ptr->get_ref_count();
if (count > 0) {
ptr->set_ref_count(count-1);
return count == 1;
}
// ERROR: zero ref count decremented
assert(0);
return false;
}
};
template <typename T, bool is_ref_counted = false>
class ref_ptr_impl
{
/// struct to store the pointer with a count
struct counter_type
{
counter_type(T* p, int c) : ptr(p), count(c) {}
T* ptr;
int count;
};
/// store pointer to counter struct
counter_type* counter;
protected:
/// decrement the count, delete if it is 0
void release()
{
if (counter) {
if (--counter->count == 0) {
delete counter->ptr;
counter->ptr = 0;
delete counter;
}
counter = 0;
}
}
/// return the pointer itself
T* ref () const { return counter ? counter->ptr : 0; }
/// construct reference counted pointer
explicit ref_ptr_impl(T* p = 0) : counter(0) {
if (p)
counter = new counter_type(p, 1);
}
/// copy construct from same pointer type and increment count
ref_ptr_impl(const ref_ptr_impl<T,false>& r) : counter(r.counter)
{
if (counter)
++counter->count;
}
/// copy construct from pointer of derived type with virtual destructor
template <typename S>
ref_ptr_impl(const ref_ptr_impl<S,false>& s)
{
// ref_ptr conversion only valid if T is base of S
CGV_DEFINES_ASSERT(type::cond::is_base_of<T,S>::value);
// and T has a virtual destructor
CGV_DEFINES_ASSERT(type::cond::has_virtual_destructor<T>::value);
// after validity checks, set pointer
counter = static_cast<counter_type*>(s.counter);
// and increment reference count
if (counter)
++counter->count;
}
public:
/// return current count
int get_count() const { return counter ? counter->count : 0; }
};
template <typename T>
class ref_ptr_impl<T,true> : public ref_ptr_tag
{
T* ptr;
protected:
/// if the pointer had been initialized before, decrement reference count and release pointer, if necessary delete instance
void release() {
if (ptr) {
if (dec_ref_count(ptr)) {
// if (validate_delete(ptr))
delete ptr;
}
ptr = 0;
}
}
/// return the pointer itself
T* ref () const {
return ptr;
}
/// construct from pointer and increment reference count
explicit ref_ptr_impl(T* p) : ptr(p) {
if (ptr)
inc_ref_count(ptr);
}
/// copy construct from same pointer type and increment count
ref_ptr_impl(const ref_ptr_impl<T,true>& r) : ptr(r.ref())
{
if (ptr)
inc_ref_count(ptr);
}
/// copy construct from pointer of derived type with virtual destructor
template <typename S>
ref_ptr_impl(const ref_ptr_impl<S,true>& s)
{
// ref_ptr conversion only valid if T is base of S
CGV_DEFINES_ASSERT(type::cond::is_base_of<T,S>::value);
// and T has a virtual destructor
CGV_DEFINES_ASSERT(type::cond::has_virtual_destructor<T>::value);
// after validity checks, set pointer with a very bad hack!!
ptr = static_cast<const ref_ptr<S,true>&>(s).operator->();
// and increment reference count
if (ptr)
inc_ref_count(ptr);
}
public:
// void kill() { ptr = 0; }
/// return the reference count
int get_count() const {
return ptr ? ptr->get_ref_count() : 0;
}
};
/** reference counted pointer, which can work together with types that are derived
from ref_counted, in which case the reference count of ref_counted is
used. Otherwise a reference count is allocated and access to the stored instance
needs to follow two pointers. */
template <class T, bool is_ref_counted = type::cond::is_base_of<ref_counted,T>::value>
class ref_ptr : public ref_ptr_impl<T,is_ref_counted>
{
public:
/// type of the reference counted pointer
typedef ref_ptr<T,is_ref_counted> this_type;
/// type of base class that implements the reference count specific methods
typedef ref_ptr_impl<T,is_ref_counted> base_type;
public:
/// construction from pointer or empty if pointer is not given
ref_ptr(T* p = 0) : base_type(p) {}
/// copy constructor for reference pointers of the same type
ref_ptr(const this_type& r) : base_type(r) {}
/// destruct reference counted pointer
~ref_ptr() {
this->release();
}
/// allow to copy ref_ptr<S> to a ref_ptr<T> if T is a base class of S and if T has a virtual destructor
template <typename S>
ref_ptr(const ref_ptr<S,is_ref_counted>& s) : base_type(s) {}
/// use static cast to convert from T to S if T is a base class of S and has a virtual destructor
template <typename S>
ref_ptr<S,is_ref_counted> up_cast() const {
// ref_ptr conversion only valid if T is base of S
CGV_DEFINES_ASSERT(type::cond::is_base_of<T,S>::value);
// and S has a virtual destructor
CGV_DEFINES_ASSERT(type::cond::has_virtual_destructor<T>::value);
// after validity checks, return converted pointer
return ref_ptr<S,is_ref_counted>(
*reinterpret_cast<const ref_ptr<S,is_ref_counted>*>(this)
);
}
/// assignment to pointer of same type
this_type& operator = (const this_type& r) {
if (this == &r)
return *this;
this->release();
new (this) this_type(r);
return *this;
}
/// assignment to pointer of derived type with virtual destructor
template <typename S>
this_type& operator = (const ref_ptr<S,is_ref_counted>& r) {
if (this == (const this_type*)&r)
return *this;
return *this = this_type(r);
}
/// access to element
T& operator*() const {
return *this->ref();
}
/// access to element pointer
T* operator->() const {
return this->ref();
}
/// compare by pointer
bool operator == (const this_type& r) const {
return this->ref() == r.ref();
}
/// compare by pointer
bool operator < (const this_type& r) const {
return this->ref() < r.ref();
}
/// compare by pointer
bool operator != (const this_type& r) const {
return this->ref() != r.ref();
}
/// check if this is the only reference
bool unique() const {
return this->get_count() <= 1;
}
/// check if pointer is not yet set
bool empty() const {
return this->get_count() == 0;
}
/// conversion to bool results in false if the stored pointer is a null pointer
operator bool () const {
return !empty();
}
/// set to null pointer
void clear() {
this->release();
}
};
}
}
#include <cgv/config/lib_end.h>

View file

@ -0,0 +1,41 @@
#pragma once
#include <vector>
namespace cgv {
namespace data {
struct union_find : public std::vector<unsigned int>
{
/// construct with given number of elements
union_find(unsigned int n) { init(n); }
/// init such that each element is a representative
void init(unsigned int n) {
resize(n);
for (unsigned int i=0; i<n; ++i)
at(i) = i;
}
/// find representative with path compression
unsigned int find(unsigned int i)
{
// find representative j
unsigned int j = i;
while (at(j) != j)
j = at(j);
// compress path
while (i != j) {
unsigned int tmp = at(i);
at(i) = j;
i = tmp;
}
return j;
}
/// union of two groups
void unify(unsigned int i, unsigned int j)
{
at(find(i)) = j;
}
};
}
}

View file

@ -0,0 +1,19 @@
#pragma once
#include <cgv/defines/join.h>
namespace cgv {
namespace defines {
template <bool x> struct STATIC_ASSERTION_FAILURE;
template <> struct STATIC_ASSERTION_FAILURE<true> { enum { value = 1 }; };
template<int x> struct static_assert_test{};
}
}
#define CGV_DEFINES_ASSERT( ... ) \
typedef ::cgv::defines::static_assert_test<\
sizeof(::cgv::defines::STATIC_ASSERTION_FAILURE< (bool)( __VA_ARGS__ ) >)>\
CGV_DEFINES_JOIN(_static_assert_test_, __LINE__);

View file

@ -0,0 +1,6 @@
#pragma once
/// join two arguments
#define CGV_DEFINES_JOIN( X, Y ) CGV_DEFINES_DO_JOIN( X, Y )
#define CGV_DEFINES_DO_JOIN( X, Y ) CGV_DEFINES_DO_JOIN2(X,Y)
#define CGV_DEFINES_DO_JOIN2( X, Y ) X##Y

View file

@ -0,0 +1,5 @@
#pragma once
// helper define for QUOTE_SYMBOL_VALUE
#define QUOTE_SYMBOL_VALUE_(x) #x
/// this macro encloses the value of a defined symbol in double quotes as needed for a string constant
#define QUOTE_SYMBOL_VALUE(x) QUOTE_SYMBOL_VALUE_(x)

View file

@ -0,0 +1,37 @@
#pragma once
#include <string>
#include "window.h"
#include "lib_begin.h"
namespace cgv {
/// namespace that holds the abstract gui interface
namespace gui {
/// the application class is only a container for static methods that give access to the windows of the application
class CGV_API application
{
public:
/// create a window of the given %type, where all %gui implementations must support the %type "viewer"
static window_ptr create_window(int w, int h,
const std::string& title, const std::string& window_type = "viewer");
/// set the input focus to the given window
static bool set_focus(const_window_ptr);
/// return the number of created windows
static unsigned int get_nr_windows();
/// return the i-th created window
static window_ptr get_window(unsigned int i);
/// run the main loop of the %window system
static bool run();
/// quit the %application by closing all windows
static void quit(int exit_code = 0);
/// copy text to the clipboard
static void copy_to_clipboard(const std::string& s);
/// retreive text from clipboard
static std::string paste_from_clipboard();
};
}
}
#include <cgv/config/lib_end.h>

View file

@ -0,0 +1,65 @@
#pragma once
#include <cgv/base/base.h>
#include <cgv/gui/provider.h>
#include "lib_begin.h"
namespace cgv {
namespace gui {
///
class CGV_API base_provider : public cgv::base::base, public provider
{
protected:
std::string parent_type, parent_options;
cgv::base::base_ptr instance;
std::string textual_gui_definition;
bool is_named_gui_assignment_m;
unsigned nr_toggles;
bool* toggles;
enum ParsingTasks { PT_NR_TOGGLES, PT_INIT_TOGGLES, PT_CREATE_GUI };
void parse_definition(ParsingTasks pt);
std::string error_start(const char* ptr) const;
bool find_member(const std::string& name, void*& member_ptr, std::string& member_type);
public:
/// construct from instance and gui definition
base_provider(cgv::base::base_ptr _instance = cgv::base::base_ptr(),
const std::string& gui_def = "", bool _is_named_gui_assignment = false);
/// construct from gui definition file and instance
base_provider(const std::string& file_name,
cgv::base::base_ptr _instance = cgv::base::base_ptr());
/// destruct base provider
~base_provider();
///
bool self_reflect(cgv::reflect::reflection_handler& rh);
///
std::string get_parent_type() const;
/// overload to return the type name of this object. By default the type interface is queried over get_type.
std::string get_type_name() const;
///
data::ref_ptr<cgv::base::named,true> get_named();
///
void read_gui_definition(const std::string& file_name);
///
void set_gui_definition(const std::string& new_def);
///
const std::string& get_gui_definition() const;
///
bool is_named_gui_assignment() const { return is_named_gui_assignment_m; }
///
void set_named_gui_assignment(bool value = true) { is_named_gui_assignment_m = value; }
///
void set_instance(cgv::base::base_ptr _instance);
///
cgv::base::base_ptr get_instance() const;
///
void create_gui();
};
typedef cgv::data::ref_ptr<base_provider> base_provider_ptr;
}
}
#include <cgv/config/lib_end.h>

View file

@ -0,0 +1,66 @@
#pragma once
#include <cgv/base/register.h>
#include <string>
#include "base_provider.h"
#include "lib_begin.h"
namespace cgv {
namespace gui {
///
class CGV_API base_provider_generator : public cgv::base::base, public cgv::signal::tacker, public cgv::base::registration_listener
{
protected:
/// each gui definition consists of the textual definition as well as an options string
struct gui_definition {
std::string definition;
std::string options;
gui_definition(const std::string& _def="", const std::string& _opt="") : definition(_def), options(_opt) {}
};
/// type of mapping from strings to gui definitions
typedef std::map<std::string,gui_definition> def_map_type;
/// iterator type for map
typedef def_map_type::const_iterator def_map_iter;
/// type of map from objects to base_providers
typedef std::map<cgv::base::base_ptr,base_provider_ptr> pvd_map_type;
/// iterator type of base_provider map
typedef pvd_map_type::iterator pvd_map_iter;
/// mappings from type to gui definitions
def_map_type defs_by_type;
/// mappings from name to gui definitions
def_map_type defs_by_name;
/// keep track of unmatched objects
std::vector<cgv::base::base_ptr> unmatched_objects;
/// store map to base_providers
pvd_map_type providers;
/// check whether gui description is available for object and if yes generate a base_provider
bool generate_object_gui(base_ptr object);
/// store read gui files with last write times
std::map<std::string,long long> gui_files;
/// whether to check files
bool check_file_update;
///
void timer_event(double,double);
public:
/// construct from instance and gui definition
base_provider_generator();
///
std::string get_type_name() const;
///
bool self_reflect(cgv::reflect::reflection_handler& rh);
///
void on_set(void* member_ptr);
/// parse file and extract gui definitions
bool parse_gui_file(const std::string& file_name);
/// if object is registered that does not provide its own gui but matches type or name of a parsed gui definition, register a newly created base_provider for the object
void register_object(cgv::base::base_ptr object, const std::string& options);
/// remove also the base_provider of an object if created
void unregister_object(cgv::base::base_ptr object, const std::string& options);
};
}
}
#include <cgv/config/lib_end.h>

View file

@ -0,0 +1,34 @@
#pragma once
#include <cgv/base/node.h>
#include <cgv/signal/signal.h>
#include <cgv/data/ref_ptr.h>
#include "lib_begin.h"
namespace cgv {
namespace gui {
/// %gui independent %button class that provides a click signal
class CGV_API button : public base::node
{
public:
/// construct from name
button(const std::string& name = "");
/// overload to return the type name of this object
std::string get_type_name() const;
/// this signal is sent when the user presses the %button
cgv::signal::signal<button&> click;
};
/// ref counted pointer to button
typedef data::ref_ptr<button> button_ptr;
#if _MSC_VER >= 1400
CGV_TEMPLATE template class CGV_API data::ref_ptr<button>;
#endif
}
}
#include <cgv/config/lib_end.h>

View file

@ -0,0 +1,170 @@
#pragma once
#include "view.h"
#include <cgv/signal/signal.h>
#include "lib_begin.h"
namespace cgv {
namespace gui {
/// %gui and %type independent %base class of all controls
class CGV_API abst_control : public abst_view
{
public:
/// construct from name
abst_control(const std::string& name);
/// add default implementation passing the query to the controls() method
bool shows(const void* ptr) const;
/// return whether the control controls the value pointed to by ptr
virtual bool controls(const void* ptr) const = 0;
/// attach a functor to the value change signal
virtual void attach_to_value_change(cgv::signal::functor_base* func) = 0;
/// attach a functor to the value change signal
virtual void attach_to_check_value(cgv::signal::functor_base* bool_func) = 0;
};
/// ref counted pointer to abst %control
typedef data::ref_ptr<abst_control> control_ptr;
#if _MSC_VER >= 1400
CGV_TEMPLATE template class CGV_API data::ref_ptr<abst_control>;
#endif
/// %type independent %base class of %control %provider interface
struct abst_control_provider
{
//! overload to check if ptr points to the controlled value
/*! The method is used when searching controls with find_control.
The default implementation compares ptr to get_value_void(). */
virtual bool controls(const void* ptr, void* user_data) const = 0;
};
/*! reimplement the %control %provider for a customized control.
A %control %provider can be used as argument to the constructor
of the control class. The provider class also implements an
overloaded version of the add_control method that takes a
%control %provider as second argument instead of the reference
to a value. */
template <typename T>
struct control_provider : public abst_control_provider
{
/// overload to set the value
virtual void set_value(const T& value, void* user_data) = 0;
/// overload to get the value
virtual const T get_value(void* user_data) const = 0;
/// the default implementation compares ptr to &get_value().
virtual bool controls(const void* ptr, void* user_data) const { return false; }
};
/*! gui independent control of a value that has the type of the template argument.
The value can either be specified as a reference or through the control_provider
that implements a get and a set method.
Before the control changes a value, it
emits the signal check_value to test if the new value is valid. The check_value
signal has a boolean return value. All attached callbacks must return true in order
for the check to be successful. The attached callbacks can also change the new value
to a valid value. The check_value callbacks should use the get_new_value(), get_value()
and set_new_value() methods of the control to update the new value and to access the
current value that has not been changed yet.
If the validity check is successful, the value is changed to the new value and the
value_change signal is emitted. The callbacks attached to this signal can not only
query the current value with get_value() but also the old value with get_old_value().
Take care that the get_old_value() cannot be used in the callbacks attached to
check_value and the get_new_value() method cannot be used in the callbacks attached
to the value_change signal.
*/
template <typename T>
class control : public abst_control
{
private:
T* value_ptr;
control_provider<T>* cp;
T new_value;
protected:
// protected function for the setter
void set_value(const T& v) {
if (cp)
cp->set_value(v, value_ptr);
else {
*value_ptr = v;
update_views();
}
}
public:
/// type of the value check signal
typedef cgv::signal::bool_signal<control<T>&> value_check_signal_type;
/// type of the value change signal
typedef cgv::signal::signal<control<T>&> value_change_signal_type;
/// construct abstract element from reference to value
control(const std::string& _name, T& _value) : abst_control(_name), value_ptr(&_value), new_value(_value), cp(0) {
attach_to_reference(value_ptr);
}
/// construct abstract element from control_provider
control(const std::string& _name, T* _value) : abst_control(_name) {
value_ptr = _value;
new_value = *_value;
cp = 0;
attach_to_reference(value_ptr);
}
//! this constructor allows contruction from control_provider with user data or if the pointer
//! to the control_provider is null, interpret the pointer to the user data as the value pointer
//! and act as the previous constructor.
control(const std::string& _name, abst_control_provider* _cp, void* user_data) : abst_control(_name), cp(0) {
if (_cp) {
cp = static_cast<control_provider<T>*>(_cp);
(void*&)value_ptr = user_data;
new_value = cp->get_value(user_data);
}
else {
value_ptr = (T*)user_data;
new_value = *value_ptr;
attach_to_reference(value_ptr);
}
}
//! this signal is sent when the user triggered a change of value in order to check whether the new value is valid.
/*! Use get_new_value() and set_new_value() to get and correct the new value. Return true if the new
value is ok or could be corrected, false otherwise. */
cgv::signal::bool_signal<control<T>&> check_value;
//! this signal is sent after the user triggered a change of value and the check_value succeeded.
/*! You can access the old value with get_old_value() method. */
cgv::signal::signal<control<T>&> value_change;
/// return a reference to the current value
const T get_value() const { return cp ? cp->get_value(value_ptr) : *value_ptr; }
/// return the new value to the callbacks attached to the check_value signal
const T& get_new_value() const { return new_value; }
/// set a different new value from the callbacks attached to the check_value signal
void set_new_value(const T& nv) { new_value = nv; }
/// return the old value to the callbacks attached to the change_value signal
const T& get_old_value() const { return new_value; }
/// set new value only if check_value signal succeeds and send value_change signal. Return true if value has been changed.
bool check_and_set_value(const T& nv) {
set_new_value(nv);
if (check_value(*this)) {
T tmp_value = get_value();
set_value(this->get_new_value());
set_new_value(tmp_value);
value_change(*this);
return true;
}
return false;
}
/// check whether the value represented by this element is pointing to the passed pointer
bool controls(const void* ptr) const { return cp ? cp->controls(ptr,value_ptr) : (value_ptr == ptr); }
/// attach a functor to the value change signal
void attach_to_value_change(cgv::signal::functor_base* func) {
value_change.connect_abst(func);
}
/// attach a functor to the value change signal
void attach_to_check_value(cgv::signal::functor_base* bool_func) {
check_value.connect_abst(bool_func);
}
};
}
}
#include <cgv/config/lib_end.h>

View file

@ -0,0 +1,44 @@
#pragma once
#include <string>
#include <vector>
#include <cgv/gui/window.h>
#include "lib_begin.h"
namespace cgv {
namespace gui {
/// tell the user something with a message box
extern CGV_API void message(const std::string& _message);
/// ask the user with \c question to select one of the \c answers, where \c default_answer specifies index of default answer
extern CGV_API int question(const std::string& question, const std::vector<std::string>& answers, int default_answer = -1);
/// second question interface, where \c answers is a comma seprated list of enum declaration
extern CGV_API int question(const std::string& question, const std::string& answers, int default_answer = -1);
//! query the user for a text, where the second parameter is the default \c text as well as the returned text.
/*! If \c password is true, the text is hidden. The function returns false if the user canceled the input of if no gui driver is available. */
extern CGV_API bool query(const std::string& question, std::string& text, bool password = false);
/** use this class to construct and execute a modal dialog. */
class CGV_API dialog
{
bool adjust_size;
bool result;
protected:
cgv::gui::window_ptr D;
static void set_true_and_hide(bool* result, cgv::gui::window* w);
public:
/// create from title and adjust size according to content
dialog(const std::string& title, const std::string& group_type = "align_group");
/// create from dimensions and title
dialog(int w, int h, const std::string& title, const std::string& group_type = "align_group");
/// return the gui group to which new elements are to be add
cgv::gui::gui_group_ptr group();
/// add buttons for ok and or cancel
void add_std_buttons(const std::string& ok_label = "ok", const std::string& cancel_label = "");
/// execute modal dialog and freeze all other windows
bool exec();
};
}
}
#include <cgv/config/lib_end.h>

View file

@ -0,0 +1,104 @@
#pragma once
#include <iostream>
#include "lib_begin.h"
namespace cgv {
namespace gui {
/// define the ids of the most common events
enum EventId
{
EID_NONE, //!< undefined %event id
EID_KEY, //!< id for key %event
EID_MOUSE //!< id for mouse %event
};
/// flags
enum EventFlags
{
EF_NONE = 0,
EF_MULTI = 1, //!< whether event is tagged with id of the device that generated the event
EF_DND = 2 //!< whether mouse has a drag and drop target attached
};
/// define constants for event modifiers
enum EventModifier
{
EM_SHIFT = 1, //!< shift modifier
EM_ALT = 2, //!< alt modifier
EM_CTRL = 4, //!< ctrl modifier
EM_META = 8 //!< meta modifier (windows or mac key)
};
/// define constants for toggle keys
enum EventToggleKeys
{
ETK_CAPS_LOCK = 1, //!< caps lock
ETK_NUM_LOCK = 2, //!< num lock
ETK_SCROLL_LOCK = 4 //!< scroll lock
};
/*! most simple event class that holds an id, modifiers, toggle keys and the event time.
All other event classes are derived from this. */
class CGV_API event
{
protected:
/// store which kind of event we have
unsigned char kind;
/// store event flags
unsigned char flags;
/// store the active modifiers
unsigned char modifiers;
/// store the active toggle keys
unsigned char toggle_keys;
/// store the time of the event
double time;
public:
/// construct %event from its kind
event(unsigned int _kind = EID_NONE, unsigned char _modifiers = 0, unsigned char _toggle_keys = 0, double _time = 0);
/// virtual destructor for events
virtual ~event();
/// write to stream
virtual void stream_out(std::ostream& os) const;
/// read from stream
virtual void stream_in(std::istream& is);
/// set the kind of the %event
void set_kind(unsigned char _kind);
/// return, what kind of %event this is, typically a value from the #EventId enum
unsigned get_kind() const;
/// set the event flags
void set_flags(unsigned char _flags);
/// return the event flags
unsigned get_flags() const;
/// set the modifiers
void set_modifiers(unsigned char _modifiers);
/// return the active modifiers as values from #EventModifier combined with a logical or-operation
unsigned char get_modifiers() const;
/// set the state of the toggle keys
void set_toggle_keys(unsigned char _toggle_keys);
/// return the state of the toggle keys as values from #EventToggleKeys combined with a logical or-operation
unsigned char get_toggle_keys() const;
/// set the time of the %event
void set_time(const double& _time);
/// return the time of the %event in seconds
double get_time() const;
};
/// convert a modifier combination into a readable string ending on a '+' sign if not empty, i.e. "Shift+Ctrl+"
extern CGV_API std::string get_modifier_string(unsigned char modifiers);
/// convert a toggle key combination into a readable string separated by '+' signs, i.e. "CapsLock+NumLock"
extern CGV_API std::string get_toggle_keys_string(unsigned char toggle_keys);
/// read modifiers in string format from a stream and set the passed reference to EventModifier s ored together.
extern CGV_API unsigned char stream_in_modifiers(std::istream& is);
/// read toggle keys in string format from a stream and set the passed reference to EventToggleKeys ored together.
extern CGV_API void stream_in_toggle_keys(std::istream& is, unsigned char& toggle_keys);
}
}
#include <cgv/config/lib_end.h>

View file

@ -0,0 +1,37 @@
#pragma once
#include <cgv/base/group.h>
#include <cgv/base/traverser.h>
#include "event.h"
#include "control.h"
#include "lib_begin.h"
namespace cgv {
namespace gui {
/// interface for all classes that want to receive events
class CGV_API event_handler : public base::traverse_policy
{
protected:
//std::vector<abst_control>
public:
/// default construction
event_handler();
/// grab the focus in all parent nodes
bool grab_focus();
/// overload and implement this method to handle events
virtual bool handle(event& e) = 0;
/// overload to stream help information to the given output stream
virtual void stream_help(std::ostream& os) = 0;
//! add a key control for the given property with the given options.
/*! This should be called in classes derived from cgv::base::group and event_handler. The group argument should
be the this pointer cast to cgv::base_group. If group is not given, a dynamic_cast is performed on the this
pointer. */
bool add_key_control(const std::string& property, const std::string& options, cgv::base::group_ptr group = cgv::base::group_ptr());
};
}
}
#include <cgv/config/lib_end.h>

View file

@ -0,0 +1,34 @@
#pragma once
#include <string>
#include <vector>
#include "lib_begin.h"
namespace cgv {
namespace gui {
/** ask the user for a file name to open a file.
The filter string is composed of '|'-separated pairs of the form '<text>:<filter>', where
<text> is an arbitrary text (without '|' and ':' symbols) shown with the filter and <filter>
is one filter string or a ';'-separated list of filters. For example the filter parameter could
be set to "Image Files (jpg,gif):*.jpg;*.gif|Video Files (avi):*.avi|All Files:*.*".
The path parameter can be used to define an initial directory and or an initial file for the dialog:
- if path is empty no initial directory not path are selected,
- if path defines a directory, it is used as initial directory without initial file,
- if path defines file without directory the initial file is set and the standard directory is used
- if path defines a directory and file, both initial directory and file are set.
*/
extern CGV_API std::string file_open_dialog(const std::string& title, const std::string& filter, const std::string& path = "");
/// ask user for an open dialog that can select multiple files, return common path prefix and fill field of filenames
extern CGV_API std::string files_open_dialog(std::vector<std::string>& file_names, const std::string& title, const std::string& filter, const std::string& path = "");
/** ask the user for an existing directory. */
extern CGV_API std::string directory_open_dialog(const std::string& title, const std::string& path = "");
/** ask the user for a new directory. */
extern CGV_API std::string directory_save_dialog(const std::string& title, const std::string& path = "");
/** ask the user for a file name to save a file. The filter string uses the syntax defined in the docu of
file_open_dialog(). */
extern CGV_API std::string file_save_dialog(const std::string& title, const std::string& filter, const std::string& path = "");
}
}
#include <cgv/config/lib_end.h>

View file

@ -0,0 +1,43 @@
#pragma once
#include <string>
#include "lib_begin.h"
namespace cgv {
namespace gui {
class provider;
/// interface for gui creators
struct gui_creator
{
/// attempt to create a gui and return whether this was successful
virtual bool create(provider* p, const std::string& label,
void* value_ptr, const std::string& value_type,
const std::string& gui_type, const std::string& options, bool* toggles) = 0;
};
/// register a gui creator
extern CGV_API void register_gui_creator(gui_creator* gc, const char* creator_name);
/// create the gui for a composed structure
extern CGV_API bool create_gui(provider* p, const std::string& label,
void* value_ptr, const std::string& value_type,
const std::string& gui_type = "", const std::string& options = "", bool* toggles = 0);
/// helper template for registration of gui creators
template <class T>
class gui_creator_registration
{
public:
gui_creator_registration(const char* creator_name) {
register_gui_creator(new T(), creator_name);
}
};
}
}
#include <cgv/config/lib_end.h>

View file

@ -0,0 +1,133 @@
#pragma once
#include <string>
#include <cgv/base/base.h>
#include <cgv/signal/signal.h>
#include <cgv/data/ref_counted.h>
#include "button.h"
#include "gui_group.h"
#include "view.h"
#include "control.h"
#include "window.h"
#include "text_editor.h"
#include "lib_begin.h"
namespace cgv {
namespace gui {
/// abstract %base class for %gui drivers
class CGV_API gui_driver : public cgv::base::base, public cgv::base::driver
{
public:
/**@name application management*/
//@{
/// create a window of the given type. Currently only the types "viewer with gui", "viewer" and "gui" are supported
virtual window_ptr create_window(int w, int h, const std::string& title, const std::string& window_type) = 0;
/// set the input focus to the given window
virtual bool set_focus(const_window_ptr) = 0;
/// return the number of created windows
virtual unsigned int get_nr_windows() = 0;
/// return the i-th created window
virtual window_ptr get_window(unsigned int i) = 0;
/// run the main loop of the window system
virtual bool run() = 0;
/// quit the application by closing all windows
virtual void quit(int exit_code) = 0;
/// copy text to the clipboard
virtual void copy_to_clipboard(const std::string& s) = 0;
/// retreive text from clipboard
virtual std::string paste_from_clipboard() = 0;
//@}
/**@name some basic functionality */
//@{
/// ask the user with \c _question to select one of the \c answers, where \c default_answer specifies index of default answer
virtual int question(const std::string& _question, const std::vector<std::string>& answers, int default_answer = -1) = 0;
//! query the user for a text, where the second parameter is the default \c text as well as the returned text.
/*! If \c password is true, the text is hidden. The function returns false if the user canceled the input of if no gui driver is available. */
virtual bool query(const std::string& question, std::string& text, bool password = false) = 0;
/// create a text editor
virtual text_editor_ptr create_text_editor(unsigned int w, unsigned int h, const std::string& title, int x, int y) = 0;
/// ask user for an open dialog that can select multiple files, return common path prefix and fill field of filenames
virtual std::string files_open_dialog(std::vector<std::string>& file_names, const std::string& title, const std::string& filter, const std::string& path) = 0;
/// ask user for a file to open
virtual std::string file_open_dialog(const std::string& title, const std::string& filter, const std::string& path) = 0;
/// ask user for a file to save
virtual std::string file_save_dialog(const std::string& title, const std::string& filter, const std::string& path) = 0;
//@}
/**@name threading based functionality */
//@{
//! lock the main thread of the gui from a child thread before any gui specific call.
/*! If lock is called several times, the child thread must call unlock the same number of times */
virtual void lock() = 0;
/// unlock the main thread
virtual void unlock() = 0;
//! wake main thread.
/*! Ensures that main thead is not going to
sleep any longer with the given message, that can be
queried by the main thread with get_wakeup_message(). */
virtual void wake(const std::string& message = "") = 0;
/// return the message send by the thread that woke up the main thread with wake()
virtual std::string get_wakeup_message() = 0;
/// let the main thread sleep for the given number of seconds
virtual void sleep(float time_in_seconds) = 0;
//@}
/**@name gui elements */
//@{
/// process the gui declarations in the given gui file
virtual bool process_gui_file(const std::string& file_name) = 0;
/// add a new gui group to the given parent group
virtual gui_group_ptr add_group(gui_group_ptr parent, const std::string& label, const std::string& group_type, const std::string& options, const std::string& align) = 0;
/// add a newly created decorator to the parent group
virtual base_ptr add_decorator(gui_group_ptr parent, const std::string& label, const std::string& decorator_type, const std::string& options, const std::string& align) = 0;
/// add new button to the parent group
virtual button_ptr add_button(gui_group_ptr parent, const std::string& label, const std::string& options, const std::string& align) = 0;
/// add new view to the parent group
virtual view_ptr add_view(gui_group_ptr parent, const std::string& label, const void* value_ptr, const std::string& value_type, const std::string& gui_type, const std::string& options, const std::string& align) = 0;
/// find a view in the group
virtual view_ptr find_view(gui_group_ptr parent, const void* value_ptr, int* idx_ptr) = 0;
/// add new control to the parent group
virtual control_ptr add_control(gui_group_ptr parent, const std::string& label, void* value_ptr, abst_control_provider* acp, const std::string& value_type, const std::string& gui_type, const std::string& options, const std::string& align) = 0;
/// find a control in a group
virtual control_ptr find_control(gui_group_ptr parent, void* value_ptr, int* idx_ptr) = 0;
//@}
/**@name menu elements */
//@{
/// add a newly created decorator to the menu
virtual base_ptr add_menu_separator(const std::string& menu_path) = 0;
/// use the current gui driver to append a new button in the menu, where menu path is a '/' separated path
virtual button_ptr add_menu_button(const std::string& menu_path, const std::string& options) = 0;
/// use this to add a new control to the gui with a given value type, gui type and init options
virtual data::ref_ptr<control<bool> > add_menu_bool_control(const std::string& menu_path, bool& value, const std::string& options) = 0;
/// return the element of the given menu path
virtual base_ptr find_menu_element(const std::string& menu_path) const = 0;
/// remove a single element from the gui
virtual void remove_menu_element(base_ptr) = 0;
//@}
};
/// ref counted pointer to driver
typedef data::ref_ptr<gui_driver> gui_driver_ptr;
#if _MSC_VER >= 1400
CGV_TEMPLATE template class CGV_API data::ref_ptr<gui_driver>;
#endif
/// return the currently registered gui driver or an empty pointer if non has been registered
extern CGV_API gui_driver_ptr get_gui_driver();
//! register a new gui driver.
/*! This overwrites a previously registered gui driver and should
be called in the on_register method of the driver*/
extern CGV_API void register_gui_driver(gui_driver_ptr _driver);
/// a signal that is emitted when a gui driver is registered
extern CGV_API cgv::signal::signal<gui_driver_ptr>& on_gui_driver_registration();
}
}
#include <cgv/config/lib_end.h>

View file

@ -0,0 +1,212 @@
#pragma once
#include <cgv/base/group.h>
#include <cgv/type/cond/is_enum.h>
#include <cgv/type/info/type_name.h>
#include <cgv/base/register.h>
#include "button.h"
#include "view.h"
#include "control.h"
#include "lib_begin.h"
using cgv::base::base_ptr;
template <typename T, bool is_enum = cgv::type::cond::is_enum<T>::value>
struct enum_aware_type_name : public cgv::type::info::type_name<T>
{
};
template <typename T>
struct enum_aware_type_name<T,true>
{
static const char* get_name() { return "enum"; }
};
namespace cgv {
namespace gui {
class CGV_API gui_group;
class CGV_API provider;
/// ref counted pointer to a %gui %group
typedef data::ref_ptr<gui_group,true> gui_group_ptr;
/// ref counted pointer to const %gui %group
typedef data::ref_ptr<const gui_group,true> const_gui_group_ptr;
/// %gui independent group class which is a container for %gui elements
class CGV_API gui_group : public cgv::base::group, public cgv::base::registration_listener
{
protected:
friend class provider;
/// managed objects can be add to the group such that
std::vector<cgv::base::base_ptr> managed_objects;
/// access to protected provider method
static void set_provider_parent(provider* p, gui_group_ptr g);
/// %driver specific handle for the group gui element managing the gui built in the provider
static gui_group_ptr get_provider_parent(const provider* p);
/// interface of adding an object
void register_object(cgv::base::base_ptr object, const std::string& options);
///
void unregister_object(cgv::base::base_ptr object, const std::string& options);
public:
/// construct from name
gui_group(const std::string& name = "");
/// overload to return the %type name of this object
std::string get_type_name() const;
/**@name managed objects */
//@{
//! add the passed object as an managed object.
/*! This will simply add a reference counted pointer to the object into a list
of managed elements. This pointer is released whenever the gui group is
destroyed or when the gui is recreated. This functionality can be used by
gui_creators to manage objects that are not managed by the user of the gui
library. An example usage can be found in the bit_field_controler found in the
plugin plugins/cg_ext. */
void add_managed_objects(cgv::base::base_ptr object);
/// release all managed objects
void release_all_managed_objects();
/// release a specific managed object
void release_managed_objects(cgv::base::base_ptr object);
/// check whether an object is managed by this gui group
bool is_managed_object(cgv::base::base_ptr object);
//@/
/**@name selection of children */
//@{
/// return whether several children of the group can be selected at the same time
virtual bool multiple_selection() const;
//! select the ci-th child of the group.
/*! If multiple_selection() returns true, the \c exclusive flag can be used to
unselect all other previously selected children except the newly selected
one. Typically, an exclusively selected child will gain input focus. */
virtual void select_child(unsigned ci, bool exclusive = false);
/// same as version with child index
virtual void select_child(base_ptr ci, bool exclusive = false);
//! unselect the ci-th child.
/*! If no multiple_selection is allowed, unselection can fail if the group does
not support an empty selection.*/
virtual bool unselect_child(unsigned ci);
/// same as version with child index
virtual bool unselect_child(base_ptr ci);
//! return the index of the currently selected child.
/*! In case of multiple_selection, this function returns the index of the first selected child.
In this case it can also happen that the returned index is -1 if no child is selected. */
virtual int get_selected_child_index() const;
//! return the currently selected child.
/*! In case of multiple_selection, this function returns the first selected child.
In this case it can also happen that the returned base_ptr is empty if no child
is selected. */
virtual base_ptr get_selected_child() const;
/// return whether the given child is selected
virtual bool is_selected(base_ptr c) const;
//! return whether the given child is selected.
/*! the implementation simply calls the virtual variant with get_child(ci). */
bool is_selected(unsigned ci) const;
//! This signal is emitted for every change of the selection of a child.
/*! The first argument is simply the pointer to the child whose selection state
has been changed. The second argument is the new selection state. */
cgv::signal::signal<base_ptr, bool> on_selection_change;
//@}
/**@name opening and closing of child groups*/
//@{
/// returns whether open and close of sub groups is allowed
virtual bool can_open_and_close() const;
/// return whether the given child is open
virtual bool is_open_child_group(gui_group_ptr g) const;
/// return whether the ci-th child is an open gui group
bool is_open_child_group(unsigned ci) const;
/// try to open given child group and return whether this was successful
virtual bool open_child_group(gui_group_ptr g);
/// try to close given child group and return whether this was successful
virtual bool close_child_group(gui_group_ptr g);
//! this signal is emitted, when a child group is opened or closed
/*! The first argument specifies the group and the second whether
it has been opened. */
cgv::signal::signal<gui_group_ptr,bool> on_open_state_change;
//@}
/**@name adding new elements to the group */
//@{
/// send pure alignment information
virtual void align(const std::string& _align);
/// add a new group to the given parent group
virtual gui_group_ptr add_group(const std::string& label, const std::string& group_type, const std::string& options, const std::string& align);
/// add a newly created decorator to the group
virtual base_ptr add_decorator(const std::string& label, const std::string& decorator_type, const std::string& options, const std::string& align);
/// add a newly created button to the group
virtual button_ptr add_button(const std::string& label, const std::string& options, const std::string& align);
/// add a newly created view to the group
virtual view_ptr add_view_void(const std::string& label, const void* value_ptr, const std::string& value_type, const std::string& gui_type, const std::string& options, const std::string& align);
/// add a newly created control to the group
virtual control_ptr add_control_void(const std::string& label, void* value_ptr, abst_control_provider* acp, const std::string& value_type, const std::string& gui_type, const std::string& options, const std::string& align, void* user_data);
/// add a newly created view to the group for the given value with the given %gui %type, init and align options
template <typename T>
inline data::ref_ptr<view<T> > add_view(const std::string& label, const T& value, const std::string& gui_type = "", const std::string& options = "", const std::string& align = "\n") {
view_ptr vp = add_view_void(label, &value,
enum_aware_type_name<T>::get_name(),
gui_type, options, align);
return vp.up_cast<view<T> >();
}
/// add a newly created control to the group for the given value with the given %gui %type, init and align options
template <typename T>
inline data::ref_ptr<control<T> > add_control(const std::string& label, T& value, const std::string& gui_type = "", const std::string& options = "", const std::string& align = "\n") {
control_ptr cp = add_control_void(label, &value, 0,
enum_aware_type_name<T>::get_name(),
gui_type, options, align, 0);
return cp.up_cast<control<T> >();
}
/// add a newly created control to the group which is controlled by a control_provider
template <typename T>
inline data::ref_ptr<control<T> > add_control(const std::string& label,
control_provider<T>* provider, const std::string& gui_type = "",
const std::string& options = "", const std::string& align = "\n", void* user_data = 0) {
control_ptr cp = add_control_void(label, 0, provider,
enum_aware_type_name<T>::get_name(),
gui_type, options, align, user_data);
return cp.up_cast<control<T> >();
}
//@}
/**@name finding elements in the group*/
//@{
/// find a gui element by name, return empty pointer if not found
base_ptr find_element(const std::string& name);
/// find a view in the group based on a const void pointer
view_ptr find_view_void(const void* value_ptr, int* idx_ptr);
/// find a control in the group based on a const void pointer
control_ptr find_control_void(void* value_ptr, int* idx_ptr);
//! find the next view of the given value in the current group.
/*! If the index
pointer is given, start at the index to which the pointer points and set
this index to the index of the child index of the found view */
template <typename T>
inline data::ref_ptr<view<T> > find_view(const T& value, int* idx_ptr=0) {
view_ptr vp = find_view_void(&value,idx_ptr);
return vp.up_cast<view<T> >();
}
//! find the next control of the given value in the current group.
/*! If the index
pointer is given, start at the index to which the pointer points and set
this index to the index of the child index of the found control */
template <typename T>
inline data::ref_ptr<control<T> > find_control(T& value, int* idx_ptr=0) {
control_ptr cp = find_control_void(&value,idx_ptr);
return cp.up_cast<control<T> >();
}
//@}
};
#if _MSC_VER >= 1400
CGV_TEMPLATE template class CGV_API data::ref_ptr<gui_group>;
CGV_TEMPLATE template class CGV_API data::ref_ptr<const gui_group>;
#endif
}
}
#include <cgv/config/lib_end.h>

View file

@ -0,0 +1,62 @@
#pragma once
#include <cgv/base/node.h>
#include "shortcut.h"
#include "control.h"
#include "event.h"
#include "event_handler.h"
#include "lib_begin.h"
namespace cgv {
namespace gui {
template <typename T>
class CGV_API key_control : public control<T>, public event_handler, public cgv::signal::tacker
{
private:
double increase_pressed_time;
double decrease_pressed_time;
protected:
T speed;
T min_value;
T max_value;
bool log_scale;
bool no_limits;
shortcut more;
shortcut less;
void change_value(double dt);
public:
key_control(const std::string& name, T& _value, const std::string& options = "");
std::string get_type_name() const;
bool self_reflect(cgv::reflect::reflection_handler& rh);
std::string get_property_declarations();
bool set_void(const std::string& property, const std::string& value_type, const void* value_ptr);
bool get_void(const std::string& property, const std::string& value_type, void* value_ptr);
void on_set(void* member_ptr);
bool handle(event& e);
void stream_help(std::ostream& os);
void timer_event(double time, double dt);
};
template <> class CGV_API key_control<bool> : public control<bool>, public event_handler
{
protected:
shortcut toggle;
void change_value(double dt);
public:
key_control(const std::string& name, bool& _value, const std::string& options = "");
std::string get_type_name() const;
std::string get_property_declarations();
bool set_void(const std::string& property, const std::string& value_type, const void* value_ptr);
bool get_void(const std::string& property, const std::string& value_type, void* value_ptr);
bool handle(event& e);
void stream_help(std::ostream& os);
};
}
}
#include <cgv/config/lib_end.h>

View file

@ -0,0 +1,51 @@
#pragma once
#include "event.h"
#include "shortcut.h"
#include "lib_begin.h"
namespace cgv {
namespace gui {
/// different actions that a key can perform
enum KeyAction {
KA_PRESS, //!< key press action
KA_RELEASE //!< key release action
};
/// class to represent all possible keyboard events with the EID_KEY
class CGV_API key_event : public event
{
protected:
/// store the pressed key
unsigned short key;
/// store whether
unsigned char action;
/// store the corresponding ascii character
unsigned char character;
public:
/// construct a key event from its textual description
key_event(unsigned short _key = 0, KeyAction _action = KA_PRESS, unsigned char _char = 0, unsigned char _modifiers = 0, unsigned char _toggle_keys = 0, double _time = 0);
/// write to stream
void stream_out(std::ostream& os) const;
/// read from stream
void stream_in(std::istream& is);
/// return the key being a capital letter, digit or a value from the Keys enum
unsigned short get_key() const;
/// set the key
void set_key(unsigned short _key);
/// return the key %event action
KeyAction get_action() const;
/// set the key %event action
void set_action(KeyAction _action);
/// return the key as a character
unsigned char get_char() const;
/// set the alpha numeric character
void set_char(unsigned char _char);
};
}
}
#include <cgv/config/lib_end.h>

View file

@ -0,0 +1,121 @@
#pragma once
#include <cgv/base/base.h>
#include <cgv/base/group.h>
#include <cgv/gui/resizable.h>
#include <cgv/signal/signal.h>
#include <cgv/signal/rebind.h>
#include <cgv/data/ref_ptr.h>
#include <cgv/type/variant.h>
#include <cgv/gui/layout_spacings.h>
#include "lib_begin.h"
using namespace cgv::base;
namespace cgv {
namespace gui {
/**
Allowed hints:
s - horizontal shrink
S - vertical shrink
x - horizontal expand
X - vertical expand
f - horizontal fill
F - vertical fill
l - align left
r - align right
c - align centered
t - align top
b - align bottom
m - align middle (between top and bottom)
*/
enum layout_hint
{
LH_HSHRINK = 1<<0,
LH_HEXPAND = 1<<1,
LH_HFILL = 1<<2,
LH_LEFT = 1<<3,
LH_CENTER = 1<<4,
LH_RIGHT = 1<<5,
LH_VSHRINK = 1<<6,
LH_VEXPAND = 1<<7,
LH_VFILL = 1<<8,
LH_TOP = 1<<9,
LH_MIDDLE = 1<<10,
LH_BOTTOM = 1<<11,
LH_HHINTS = 0,
LH_VHINTS = 6
};
// abstract class to define a layout on containers.
class CGV_API layout: public cgv::base::base
{
public:
// constructor that sets a container
layout(cgv::base::group_ptr container = 0);
// empty destructor
~layout();
// set a container to be layouted
void set_container(cgv::base::group_ptr container);
// set the spacing parameters
void set_spacings(const layout_spacings spacings);
// update children
virtual void update() {};
// resize
void resize(int w, int h);
virtual std::string get_property_declarations();
virtual bool set_void(const std::string &property, const std::string &value_type, const void *value_ptr);
virtual bool get_void(const std::string &property, const std::string &value_type, void *value_ptr);
protected:
cgv::base::group_ptr container;
int w, h, true_w, true_h;
int min_w, min_h, default_w, default_h;
layout_spacings spacings;
std::string spacings_name;
// get the layout hints for a child
int get_child_layout_hints(cgv::base::base_ptr child);
// get the layouted container
cgv::base::group_ptr get_container();
// get a child from the container.
base_ptr get_child(unsigned int i);
// get the size of a child
void get_child_size(const base_ptr child, int &width, int &height);
// set the size of a child
void set_child_size(const base_ptr child, int width, int height);
// get the default size of a child
void get_child_default_size(const base_ptr child, int &width, int &height);
// get the position of a child
void get_child_position(const base_ptr child, int &x, int &y);
// set the position of a child
void set_child_position(const base_ptr child, int x, int y);
// get the mimimum size of a child
void get_child_minimum_size(const base_ptr child, int &width, int &height);
};
/// ref counted pointer to layout
typedef cgv::data::ref_ptr<layout> layout_ptr;
}
}
#include <cgv/config/lib_end.h>

View file

@ -0,0 +1,32 @@
#pragma once
#include <cgv/gui/layout.h>
#include "lib_begin.h"
namespace cgv {
namespace gui {
// layout to arrange all children in an inline alignment
class CGV_API layout_inline: public layout
{
public:
layout_inline();
layout_inline(cgv::base::group_ptr container);
~layout_inline();
// the core update function to align the elements inline
void update();
};
/// ref counted pointer to table layout
typedef cgv::data::ref_ptr<layout_inline> layout_inline_ptr;
}
}
#include <cgv/config/lib_end.h>

View file

@ -0,0 +1,34 @@
#pragma once
#include <vector>
#include <string>
#include "lib_begin.h"
namespace cgv {
namespace gui {
// spacings in one direction
struct layout_dir_spacing {
int border; // space from the border to the elements
int element; // spaces between elements
};
// spacings in two directions that can be named
struct layout_spacings {
std::string name;
layout_dir_spacing horizontal;
layout_dir_spacing vertical;
};
// get spacings
CGV_API const layout_spacings& get_layout_spacings(std::string name);
// add spacings
CGV_API void add_layout_spacings(const layout_spacings& new_spacings);
// remove spacings
CGV_API void remove_layout_spacings(const std::string& name);
}
}
#include <cgv/config/lib_end.h>

View file

@ -0,0 +1,87 @@
#pragma once
#include <cgv/gui/layout.h>
#include <vector>
#include "lib_begin.h"
namespace cgv {
namespace gui {
// struct containing information on one cell
struct layout_table_cell {
bool can_shrink; // can this cell be shrinked?
bool can_expand; // can this cell be expanded?
bool can_fill; // can this cell fill all avalable space?
int min_size; // minimum size for this cell
int opt_size; // optimal size for this cell
int real_size;
void reset() {
can_shrink = false;
can_expand = false;
can_fill = false;
min_size = 0;
opt_size = 0;
real_size = 0;
};
};
// layout to arrange children of a group that have a size and position
// (ie. are derived from resizable) in a table
class CGV_API layout_table: public layout
{
public:
layout_table();
layout_table(cgv::base::group_ptr container);
~layout_table();
// the core update function to align the elements in a table
void update();
// standard get and set methods
std::string get_property_declarations();
bool set_void(const std::string& property, const std::string& value_type, const void* value_ptr);
bool get_void(const std::string& property, const std::string& value_type, void* value_ptr);
// get width of a column
int get_column_width(int col);
// get height of a row
int get_row_height(int row);
// get size of a cell
void get_cell_size(int row, int col, int &width, int &height);
private:
int nr_cols, nr_rows;
layout_table_cell *columns;
layout_table_cell *rows;
bool do_not_layout;
// calculate minimum and optimum size
void initialize_space_tables();
void delete_space_tables();
void update_spaces_table(layout_table_cell &element, int opt_size, int min_size, int hints, int hints_shift);
bool distribute_space(layout_table_cell *elements, int nr_elements, int new_size);
void calculate_child_size(layout_table_cell &element, int opt_size, int min_size, int hints, int hints_shift, int &new_size);
void calculate_child_pos(layout_table_cell &element, int child_size, int hints, int hints_shift, int &new_pos);
void get_sizes(layout_table_cell *elements, int nr_elements, int *opt_size, int *min_size);
void repair_default_values(int min_width, int min_height, int opt_width, int opt_height);
};
/// ref counted pointer to table layout
typedef cgv::data::ref_ptr<layout_table> layout_table_ptr;
}
}
#include <cgv/config/lib_end.h>

View file

@ -0,0 +1,8 @@
#if defined(CGV_GUI_FORCE_STATIC)
# define CGV_FORCE_STATIC_LIB
#endif
#ifdef CGV_GUI_EXPORTS
# define CGV_EXPORTS
#endif
#include <cgv/config/lib_begin.h>

View file

@ -0,0 +1,46 @@
#pragma once
#include <cgv/gui/button.h>
#include <cgv/gui/control.h>
#include "lib_begin.h"
namespace cgv {
namespace gui {
/// derive from this class to provide a gui to the current viewer
class CGV_API menu_provider //: public cgv::signal::tacker
{
protected:
/**@name creation of menu entries*/
//@{
/// add a newly created decorator to the group
base::base_ptr add_menu_separator(const std::string& menu_path);
/// use the current gui driver to append a new button in the menu, where menu path is a '/' separated path
button_ptr add_menu_button(const std::string& menu_path, const std::string& options = "");
/// use this to add a new control to the gui with a given value type, gui type and init options
data::ref_ptr<control<bool> > add_menu_bool_control(const std::string& menu_path, bool& value, const std::string& options = "");
//@}
/**@name update menu*/
//@{
/// return the element of the given menu path
base::base_ptr find_menu_element(const std::string& menu_path) const;
/// remove a single element from the gui
void remove_menu_element(base::base_ptr);
//@}
public:
/// default construction
menu_provider();
/// ensure to remove posted recreation callbacks
~menu_provider();
/// you must overload this for menu creation
virtual void create_menu() = 0;
/// you must overload this for to remove all elements from the menu again
virtual void destroy_menu() = 0;
};
}
}
#include <cgv/config/lib_end.h>

Some files were not shown because too many files have changed in this diff Show more