Initial Commit
This commit is contained in:
commit
ea6ebaa070
879 changed files with 252132 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
*.so
|
||||
framework/bin/
|
31
.vscode/launch.json
vendored
Normal file
31
.vscode/launch.json
vendored
Normal 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
6
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"C_Cpp.default.includePath": [
|
||||
"CGII/src/",
|
||||
"framework/include/"
|
||||
]
|
||||
}
|
24
.vscode/tasks.json
vendored
Normal file
24
.vscode/tasks.json
vendored
Normal 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
BIN
02_Skelettdarstellung.pdf
Normal file
Binary file not shown.
57
CGII/build/cmake/CMakeLists.txt
Normal file
57
CGII/build/cmake/CMakeLists.txt
Normal 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)
|
||||
|
||||
|
20
CGII/build/vs2015/CG II.sln
Normal file
20
CGII/build/vs2015/CG II.sln
Normal 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
|
117
CGII/build/vs2015/CGII.vcxproj
Normal file
117
CGII/build/vs2015/CGII.vcxproj
Normal 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>
|
103
CGII/build/vs2015/CGII.vcxproj.filters
Normal file
103
CGII/build/vs2015/CGII.vcxproj.filters
Normal 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>
|
17
CGII/build/vs2015/CGII.vcxproj.user
Normal file
17
CGII/build/vs2015/CGII.vcxproj.user
Normal 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>
|
20
CGII/build/vs2017/CG II.sln
Normal file
20
CGII/build/vs2017/CG II.sln
Normal 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
|
118
CGII/build/vs2017/CGII.vcxproj
Normal file
118
CGII/build/vs2017/CGII.vcxproj
Normal 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>
|
103
CGII/build/vs2017/CGII.vcxproj.filters
Normal file
103
CGII/build/vs2017/CGII.vcxproj.filters
Normal 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>
|
17
CGII/build/vs2017/CGII.vcxproj.user
Normal file
17
CGII/build/vs2017/CGII.vcxproj.user
Normal 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
82533
CGII/data/jump.amc
Normal file
File diff suppressed because it is too large
Load diff
338
CGII/data/jump.asf
Normal file
338
CGII/data/jump.asf
Normal 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
10
CGII/glsl/skinning.glfs
Normal 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
27
CGII/glsl/skinning.glgs
Normal 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
20
CGII/glsl/skinning.glvs
Normal 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
81
CGII/src/Animation.cpp
Normal 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
24
CGII/src/Animation.h
Normal 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;
|
||||
};
|
19
CGII/src/AnimationFrameBone.h
Normal file
19
CGII/src/AnimationFrameBone.h
Normal 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;
|
||||
};
|
67
CGII/src/AtomicTransform.cpp
Normal file
67
CGII/src/AtomicTransform.cpp
Normal 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
155
CGII/src/AtomicTransform.h
Normal 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
106
CGII/src/Bone.cpp
Normal 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
124
CGII/src/Bone.h
Normal 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
164
CGII/src/CGVDemo.cpp
Normal 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
56
CGII/src/CGVDemo.h
Normal 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
57
CGII/src/DataStore.cpp
Normal 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
56
CGII/src/DataStore.h
Normal 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;
|
||||
};
|
48
CGII/src/IHasBoundingBox.cpp
Normal file
48
CGII/src/IHasBoundingBox.cpp
Normal 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();
|
||||
}
|
33
CGII/src/IHasBoundingBox.h
Normal file
33
CGII/src/IHasBoundingBox.h
Normal 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
176
CGII/src/IKViewer.cpp
Normal 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
64
CGII/src/IKViewer.h
Normal 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
213
CGII/src/Mesh.cpp
Normal 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
54
CGII/src/Mesh.h
Normal 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
313
CGII/src/Skeleton.cpp
Normal 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
54
CGII/src/Skeleton.h
Normal 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
282
CGII/src/SkeletonViewer.cpp
Normal 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
71
CGII/src/SkeletonViewer.h
Normal 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;
|
||||
};
|
||||
|
103
CGII/src/SkinnedMeshViewer.cpp
Normal file
103
CGII/src/SkinnedMeshViewer.cpp
Normal 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);
|
||||
}
|
||||
}
|
48
CGII/src/SkinnedMeshViewer.h
Normal file
48
CGII/src/SkinnedMeshViewer.h
Normal 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
35
CGII/src/common.h
Normal 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 <rim(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
39
CGII/src/main.cpp
Normal 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
56
CGII/src/math_helper.h
Normal 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
48
framework/buildLinux.sh
Normal 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
|
34
framework/include/apps/cgv_viewer/main.cxx
Normal file
34
framework/include/apps/cgv_viewer/main.cxx
Normal 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;
|
||||
}
|
210
framework/include/cgv/base/action.h
Normal file
210
framework/include/cgv/base/action.h
Normal 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>
|
53
framework/include/cgv/base/attach_slot.h
Normal file
53
framework/include/cgv/base/attach_slot.h
Normal 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>
|
194
framework/include/cgv/base/base.h
Normal file
194
framework/include/cgv/base/base.h
Normal 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>
|
140
framework/include/cgv/base/base_generator.h
Normal file
140
framework/include/cgv/base/base_generator.h
Normal 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>
|
40
framework/include/cgv/base/console.h
Normal file
40
framework/include/cgv/base/console.h
Normal 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>
|
44
framework/include/cgv/base/find_action.h
Normal file
44
framework/include/cgv/base/find_action.h
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
67
framework/include/cgv/base/group.h
Normal file
67
framework/include/cgv/base/group.h
Normal 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>
|
62
framework/include/cgv/base/import.h
Normal file
62
framework/include/cgv/base/import.h
Normal 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>
|
8
framework/include/cgv/base/lib_begin.h
Normal file
8
framework/include/cgv/base/lib_begin.h
Normal 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>
|
52
framework/include/cgv/base/named.h
Normal file
52
framework/include/cgv/base/named.h
Normal 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>
|
54
framework/include/cgv/base/node.h
Normal file
54
framework/include/cgv/base/node.h
Normal 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>
|
505
framework/include/cgv/base/register.h
Normal file
505
framework/include/cgv/base/register.h
Normal 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>
|
131
framework/include/cgv/base/traverser.h
Normal file
131
framework/include/cgv/base/traverser.h
Normal 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>
|
9
framework/include/cgv/config/cpp_version.h
Normal file
9
framework/include/cgv/config/cpp_version.h
Normal 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
|
42
framework/include/cgv/config/lib_begin.h
Normal file
42
framework/include/cgv/config/lib_begin.h
Normal 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
|
3
framework/include/cgv/config/lib_end.h
Normal file
3
framework/include/cgv/config/lib_end.h
Normal file
|
@ -0,0 +1,3 @@
|
|||
#undef CGV_API
|
||||
#undef CGV_TEMPLATE
|
||||
#undef CGV_IS_STATIC
|
98
framework/include/cgv/data/ascii_io_reflection_handlers.h
Normal file
98
framework/include/cgv/data/ascii_io_reflection_handlers.h
Normal 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>
|
60
framework/include/cgv/data/binary_io_reflection_handlers.h
Normal file
60
framework/include/cgv/data/binary_io_reflection_handlers.h
Normal 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>
|
208
framework/include/cgv/data/component_format.h
Normal file
208
framework/include/cgv/data/component_format.h
Normal 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>
|
194
framework/include/cgv/data/data_format.h
Normal file
194
framework/include/cgv/data/data_format.h
Normal 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>
|
228
framework/include/cgv/data/data_view.h
Normal file
228
framework/include/cgv/data/data_view.h
Normal 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>
|
169
framework/include/cgv/data/dynamic_priority_queue.h
Normal file
169
framework/include/cgv/data/dynamic_priority_queue.h
Normal 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;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
43
framework/include/cgv/data/image_view.h
Normal file
43
framework/include/cgv/data/image_view.h
Normal 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>
|
45
framework/include/cgv/data/io_reflection_handler.h
Normal file
45
framework/include/cgv/data/io_reflection_handler.h
Normal 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>
|
8
framework/include/cgv/data/lib_begin.h
Normal file
8
framework/include/cgv/data/lib_begin.h
Normal 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>
|
73
framework/include/cgv/data/packing_info.h
Normal file
73
framework/include/cgv/data/packing_info.h
Normal 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>
|
109
framework/include/cgv/data/ref_arr.h
Normal file
109
framework/include/cgv/data/ref_arr.h
Normal 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();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
27
framework/include/cgv/data/ref_counted.h
Normal file
27
framework/include/cgv/data/ref_counted.h
Normal 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; }
|
||||
};
|
||||
|
||||
}
|
||||
}
|
245
framework/include/cgv/data/ref_ptr.h
Normal file
245
framework/include/cgv/data/ref_ptr.h
Normal 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>
|
41
framework/include/cgv/data/union_find.h
Normal file
41
framework/include/cgv/data/union_find.h
Normal 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;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
19
framework/include/cgv/defines/assert.h
Normal file
19
framework/include/cgv/defines/assert.h
Normal 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__);
|
||||
|
6
framework/include/cgv/defines/join.h
Normal file
6
framework/include/cgv/defines/join.h
Normal 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
|
5
framework/include/cgv/defines/quote.h
Normal file
5
framework/include/cgv/defines/quote.h
Normal 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)
|
37
framework/include/cgv/gui/application.h
Normal file
37
framework/include/cgv/gui/application.h
Normal 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>
|
65
framework/include/cgv/gui/base_provider.h
Normal file
65
framework/include/cgv/gui/base_provider.h
Normal 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>
|
66
framework/include/cgv/gui/base_provider_generator.h
Normal file
66
framework/include/cgv/gui/base_provider_generator.h
Normal 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>
|
34
framework/include/cgv/gui/button.h
Normal file
34
framework/include/cgv/gui/button.h
Normal 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>
|
170
framework/include/cgv/gui/control.h
Normal file
170
framework/include/cgv/gui/control.h
Normal 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>
|
44
framework/include/cgv/gui/dialog.h
Normal file
44
framework/include/cgv/gui/dialog.h
Normal 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>
|
104
framework/include/cgv/gui/event.h
Normal file
104
framework/include/cgv/gui/event.h
Normal 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>
|
37
framework/include/cgv/gui/event_handler.h
Normal file
37
framework/include/cgv/gui/event_handler.h
Normal 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>
|
34
framework/include/cgv/gui/file_dialog.h
Normal file
34
framework/include/cgv/gui/file_dialog.h
Normal 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>
|
43
framework/include/cgv/gui/gui_creator.h
Normal file
43
framework/include/cgv/gui/gui_creator.h
Normal 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>
|
133
framework/include/cgv/gui/gui_driver.h
Normal file
133
framework/include/cgv/gui/gui_driver.h
Normal 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>
|
212
framework/include/cgv/gui/gui_group.h
Normal file
212
framework/include/cgv/gui/gui_group.h
Normal 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>
|
62
framework/include/cgv/gui/key_control.h
Normal file
62
framework/include/cgv/gui/key_control.h
Normal 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>
|
51
framework/include/cgv/gui/key_event.h
Normal file
51
framework/include/cgv/gui/key_event.h
Normal 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>
|
121
framework/include/cgv/gui/layout.h
Normal file
121
framework/include/cgv/gui/layout.h
Normal 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>
|
32
framework/include/cgv/gui/layout_inline.h
Normal file
32
framework/include/cgv/gui/layout_inline.h
Normal 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>
|
34
framework/include/cgv/gui/layout_spacings.h
Normal file
34
framework/include/cgv/gui/layout_spacings.h
Normal 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>
|
87
framework/include/cgv/gui/layout_table.h
Normal file
87
framework/include/cgv/gui/layout_table.h
Normal 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>
|
8
framework/include/cgv/gui/lib_begin.h
Normal file
8
framework/include/cgv/gui/lib_begin.h
Normal 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>
|
46
framework/include/cgv/gui/menu_provider.h
Normal file
46
framework/include/cgv/gui/menu_provider.h
Normal 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
Loading…
Reference in a new issue