Initial commit: Final state of the master project

This commit is contained in:
2017-09-16 09:41:37 +02:00
commit 696180d43b
832 changed files with 169717 additions and 0 deletions

307
.gitignore vendored Normal file
View File

@@ -0,0 +1,307 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
**/Properties/launchSettings.json
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Typescript v1 declaration files
typings/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
# CodeRush
.cr/
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Project specific ignores:
*.pool
*.oct
*.bin

181
CMakeLists.txt Normal file
View File

@@ -0,0 +1,181 @@
cmake_minimum_required(VERSION 3.3)
project(CDAG)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_SOURCE_DIR}/bin/Debug/)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_SOURCE_DIR}/bin/Release/)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall")
include_directories(Research/inc/)
set(REQUIRED_LIBS GL GLU GLEW glfw tbb assimp pthread)
set(MAIN_SOURCE_FILES
Research/core/OctreeBuilder/BaseOctreeBuilder.cpp
Research/core/OctreeBuilder/BaseOctreeBuilder.h
Research/core/OctreeBuilder/ColorChannelMultiRootOctreeBuilder.h
Research/core/OctreeBuilder/ColoredOctreeBuilder.cpp
Research/core/OctreeBuilder/ColoredOctreeBuilder.h
Research/core/OctreeBuilder/ColorQuantizer.cpp
Research/core/OctreeBuilder/ColorQuantizer.h
Research/core/OctreeBuilder/CompressedTextureFactory.h
Research/core/OctreeBuilder/HierarchicalColoredOctreeBuilder.cpp
Research/core/OctreeBuilder/HierarchicalColoredOctreeBuilder.h
Research/core/OctreeBuilder/MaterialLibraryMultiRootOctreeBuilder.cpp
Research/core/OctreeBuilder/MaterialLibraryMultiRootOctreeBuilder.h
Research/core/OctreeBuilder/MaterialMultiRootOctreeBuilder.h
Research/core/OctreeBuilder/MultiBitsMultiRootOctreeBuilder.h
Research/core/OctreeBuilder/MultiRootOctreeBuilder.cpp
Research/core/OctreeBuilder/MultiRootOctreeBuilder.h
Research/core/OctreeBuilder/OctreeBuilder.cpp
Research/core/OctreeBuilder/OctreeBuilder.h
Research/core/OctreeBuilder/OctreeBuilderStatistics.h
Research/core/OctreeBuilder/OctreeConverter.cpp
Research/core/OctreeBuilder/OctreeConverter.h
Research/core/OctreeBuilder/OctreeLoader.cpp
Research/core/OctreeBuilder/OctreeLoader.h
Research/core/OctreeBuilder/PoolBuilderFactory.h
Research/core/OctreeBuilder/RandomOctreeBuilder.cpp
Research/core/OctreeBuilder/RandomOctreeBuilder.h
Research/core/OctreeBuilder/SettingsParser.cpp
Research/core/OctreeBuilder/SettingsParser.h
Research/core/OctreeBuilder/StandardOctreeBuilder.cpp
Research/core/OctreeBuilder/StandardOctreeBuilder.h
Research/core/OctreeBuilder/TreeTypeParser.cpp
Research/core/OctreeBuilder/TreeTypeParser.h
Research/core/OctreeBuilder/UniqueIndexColoredOctreeBuilder.cpp
Research/core/OctreeBuilder/UniqueIndexColoredOctreeBuilder.h
Research/core/Util/BinaryTree.h
Research/core/Util/BoolArray.cpp
Research/core/Util/BoolArray.h
Research/core/Util/BoolGrid3D.cpp
Research/core/Util/BoolGrid3D.h
Research/core/Util/ObjectPool.h
Research/core/Util/Stopwatch.cpp
Research/core/Util/Stopwatch.h
Research/core/BitHelper.h
Research/core/Camera.cpp
Research/core/Camera.h
Research/core/CameraPath.cpp
Research/core/CameraPath.h
Research/core/CollectionHelper.h
Research/core/ColorHelper.cpp
Research/core/ColorHelper.h
Research/core/Comparers.h
Research/core/CompileTimeArray.h
Research/core/Controls.cpp
Research/core/Controls.h
Research/core/Defines.h
Research/core/Hashers.h
Research/core/IntersectTests.cpp
Research/core/IntersectTests.h
Research/core/MathHelper.h
Research/core/Serializer.h
Research/core/StringHelper.cpp
Research/core/StringHelper.h
Research/scene/Material/MaterialQuantizer/ColorQuantizer/BaseColorQuantizer.h
Research/scene/Material/MaterialQuantizer/ColorQuantizer/ColorBitCutter.cpp
Research/scene/Material/MaterialQuantizer/ColorQuantizer/ColorBitCutter.h
Research/scene/Material/MaterialQuantizer/ColorQuantizer/MaxErrorClusterer.cpp
Research/scene/Material/MaterialQuantizer/ColorQuantizer/MaxErrorClusterer.h
Research/scene/Material/MaterialQuantizer/ColorQuantizer/XiangCIELABClusterer.cpp
Research/scene/Material/MaterialQuantizer/ColorQuantizer/XiangCIELABClusterer.h
Research/scene/Material/MaterialQuantizer/ColorQuantizer/XiangClusterer.cpp
Research/scene/Material/MaterialQuantizer/ColorQuantizer/XiangClusterer.h
Research/scene/Material/MaterialQuantizer/BaseQuantizer.h
Research/scene/Material/BaseMaterial.h
Research/scene/Material/BitsMaterial.h
Research/scene/Material/Block.h
Research/scene/Material/BlockBasedMaterialLibrary.h
Research/scene/Material/Color.cpp
Research/scene/Material/Color.h
Research/scene/Material/ColorChannel.cpp
Research/scene/Material/ColorChannel.h
Research/scene/Material/MaterialLibrary.h
Research/scene/Material/MaterialLibraryPointer.h
Research/scene/Octree/ChildMask.h
Research/scene/Octree/ColorChannelMultiRootTree.h
Research/scene/Octree/ColoredTree.h
Research/scene/Octree/HierarchicalColorsOnlyRoot.cpp
Research/scene/Octree/HierarchicalColorsOnlyRoot.h
Research/scene/Octree/HierarchicalMaterialMultiRoot.h
Research/scene/Octree/HierarchicalNode.cpp
Research/scene/Octree/HierarchicalNode.h
Research/scene/Octree/HierarchicalRoot.h
Research/scene/Octree/HierarchicalShiftingColoredRoot.cpp
Research/scene/Octree/HierarchicalShiftingColoredRoot.h
Research/scene/Octree/IAdditionalProperties.h
Research/scene/Octree/IBlockTexture.h
Research/scene/Octree/IMaterialTexture.h
Research/scene/Octree/LeafMaterialMultiRootTree.h
Research/scene/Octree/LeafMaterialTree.h
Research/scene/Octree/MaterialLeaf.h
Research/scene/Octree/MaterialLibraryMultiRootTree.h
Research/scene/Octree/MaterialNode.h
Research/scene/Octree/MaterialTree.h
Research/scene/Octree/MultiRoot.cpp
Research/scene/Octree/MultiRoot.h
Research/scene/Octree/MultiRootBitsTree.h
Research/scene/Octree/Node.cpp
Research/scene/Octree/Node.h
Research/scene/Octree/NodePoolSingleton.cpp
Research/scene/Octree/NodePoolSingleton.h
Research/scene/Octree/NodeReplacementFinder.h
Research/scene/Octree/NodeSmall.h
Research/scene/Octree/Root.cpp
Research/scene/Octree/Root.h
Research/scene/Octree/UniqueIndexNode.cpp
Research/scene/Octree/UniqueIndexNode.h
Research/scene/Octree/UniqueIndexRoot.h
Research/scene/PoolBuilder/AdaptivePointerPoolBuilder.cpp
Research/scene/PoolBuilder/AdaptivePointerPoolBuilder.h
Research/scene/PoolBuilder/BasePoolBuilder.h
Research/scene/PoolBuilder/BaseTreePoolBuilder.cpp
Research/scene/PoolBuilder/BaseTreePoolBuilder.h
Research/scene/PoolBuilder/OriginalPoolBuilder.h
Research/scene/PoolBuilder/StandardPoolBuilder.cpp
Research/scene/PoolBuilder/StandardPoolBuilder.h
Research/scene/PoolBuilder/VirtualNodePoolBuilder.cpp
Research/scene/PoolBuilder/VirtualNodePoolBuilder.h
Research/scene/TextureCompressor/BasicTexture.h
Research/scene/TextureCompressor/BlockCompressedTexture.h
Research/scene/TextureCompressor/BlockHashers.h
Research/scene/TextureCompressor/CompressedTexture.h
Research/scene/TextureCompressor/DagBasedTexture.h
Research/scene/TextureCompressor/MultiRootBasedTexture.h
Research/scene/TextureCompressor/PaletteBlockTexture.h
Research/scene/TextureCompressor/TightlyPackedTexture.h
Research/scene/DirectionalLight.cpp
Research/scene/DirectionalLight.h
Research/scene/Light.cpp
Research/scene/Light.h
Research/scene/ObjLoader.cpp
Research/scene/ObjLoader.h
Research/scene/PNG.cpp
Research/scene/PNG.h
Research/scene/Scene.h
Research/shaders/CombinedStackRaytrace.frag
Research/shaders/DepthPeel.frag
Research/shaders/DepthPeel.vert
Research/shaders/Raytrace1.frag
Research/shaders/RenderTexture.frag
Research/shaders/RenderTexture.vert
Research/shaders/Shader.frag
Research/shaders/Shader.vert
Research/shaders/ShaderLoader.cpp
Research/shaders/ShaderLoader.h
Research/shaders/SSAO.frag
Research/shaders/SSAO2.frag
Research/shaders/StackRaytrace.frag
Research/PropertyLoader.cpp
Research/PropertyLoader.h
Research/Renderer.cpp
Research/Renderer.h
Research/inc/lodepng/lodepng.h
Research/inc/lodepng/lodepng.cpp
)
add_executable(CDAG Research/main.cpp ${MAIN_SOURCE_FILES})
add_executable(OctreeBuilder OctreeBuilder/main.cpp ${MAIN_SOURCE_FILES})
target_link_libraries(CDAG ${REQUIRED_LIBS})
target_link_libraries(OctreeBuilder ${REQUIRED_LIBS})

View File

@@ -0,0 +1,373 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.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="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release2|Win32">
<Configuration>Release2</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release2|x64">
<Configuration>Release2</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{58AD3A6F-900A-46F6-947E-80D31DF1A60E}</ProjectGuid>
<RootNamespace>OctreeBuilder</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release2|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release2|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</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 Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<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>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release2|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release2|x64'" Label="PropertySheets">
<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'">
<LibraryPath>$(ProjectDir)\..\Research\lib32;C:\Program Files %28x86%29\Visual Leak Detector\lib\Win32;$(LibraryPath)</LibraryPath>
<IncludePath>C:\Program Files %28x86%29\Visual Leak Detector\include;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LibraryPath>$(ProjectDir)\..\Research\lib64;C:\Program Files %28x86%29\Visual Leak Detector\lib\Win64;$(LibraryPath)</LibraryPath>
<IncludePath>C:\Program Files %28x86%29\Visual Leak Detector\include;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>
</LinkIncremental>
<LibraryPath>$(ProjectDir)\..\Research\lib32;C:\Program Files %28x86%29\Visual Leak Detector\lib\Win32;$(LibraryPath)</LibraryPath>
<IncludePath>C:\Program Files %28x86%29\Visual Leak Detector\include;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release2|Win32'">
<LinkIncremental />
<LibraryPath>$(ProjectDir)\..\Research\lib32;C:\Program Files %28x86%29\Visual Leak Detector\lib\Win32;$(LibraryPath)</LibraryPath>
<IncludePath>C:\Program Files %28x86%29\Visual Leak Detector\include;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental />
<LibraryPath>$(ProjectDir)\..\Research\lib64;C:\Program Files %28x86%29\Visual Leak Detector\lib\Win64;$(LibraryPath)</LibraryPath>
<IncludePath>C:\Program Files %28x86%29\Visual Leak Detector\include;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release2|x64'">
<LinkIncremental />
<LibraryPath>$(ProjectDir)\..\Research\lib64;C:\Program Files %28x86%29\Visual Leak Detector\lib\Win64;$(LibraryPath)</LibraryPath>
<IncludePath>C:\Program Files %28x86%29\Visual Leak Detector\include;$(IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>glfw3.lib;opengl32.lib;glew32.lib;assimp.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>glfw3.lib;opengl32.lib;glew32.lib;assimp.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<RuntimeTypeInfo>true</RuntimeTypeInfo>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>glfw3.lib;opengl32.lib;glew32.lib;assimp.lib;%(AdditionalDependencies)</AdditionalDependencies>
<Profile>true</Profile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release2|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<RuntimeTypeInfo>true</RuntimeTypeInfo>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>glfw3.lib;opengl32.lib;glew32.lib;assimp.lib;%(AdditionalDependencies)</AdditionalDependencies>
<Profile>true</Profile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>glfw3.lib;opengl32.lib;glew32.lib;assimp.lib;%(AdditionalDependencies)</AdditionalDependencies>
<Profile>true</Profile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release2|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>glfw3.lib;opengl32.lib;glew32.lib;assimp.lib;%(AdditionalDependencies)</AdditionalDependencies>
<Profile>true</Profile>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\Research\core\ColorHelper.cpp" />
<ClCompile Include="..\Research\core\IntersectTests.cpp" />
<ClCompile Include="..\Research\core\OctreeBuilder\BaseOctreeBuilder.cpp" />
<ClCompile Include="..\Research\core\OctreeBuilder\ColoredOctreeBuilder.cpp" />
<ClCompile Include="..\Research\core\OctreeBuilder\ColorQuantizer.cpp" />
<ClCompile Include="..\Research\core\OctreeBuilder\HierarchicalColoredOctreeBuilder.cpp" />
<ClCompile Include="..\Research\core\OctreeBuilder\MaterialLibraryMultiRootOctreeBuilder.cpp" />
<ClCompile Include="..\Research\core\OctreeBuilder\MultiRootOctreeBuilder.cpp" />
<ClCompile Include="..\Research\core\OctreeBuilder\OctreeBuilder.cpp" />
<ClCompile Include="..\Research\core\OctreeBuilder\OctreeConverter.cpp" />
<ClCompile Include="..\Research\core\OctreeBuilder\OctreeLoader.cpp" />
<ClCompile Include="..\Research\core\OctreeBuilder\RandomOctreeBuilder.cpp" />
<ClCompile Include="..\Research\core\OctreeBuilder\SettingsParser.cpp" />
<ClCompile Include="..\Research\core\OctreeBuilder\StandardOctreeBuilder.cpp" />
<ClCompile Include="..\Research\core\OctreeBuilder\TreeTypeParser.cpp" />
<ClCompile Include="..\Research\core\OctreeBuilder\UniqueIndexColoredOctreeBuilder.cpp" />
<ClCompile Include="..\Research\core\StringHelper.cpp" />
<ClCompile Include="..\Research\core\Util\BoolArray.cpp" />
<ClCompile Include="..\Research\core\Util\Stopwatch.cpp" />
<ClCompile Include="..\Research\inc\lodepng\lodepng.cpp" />
<ClCompile Include="..\Research\PropertyLoader.cpp" />
<ClCompile Include="..\Research\scene\Material\Color.cpp" />
<ClCompile Include="..\Research\scene\Material\ColorChannel.cpp" />
<ClCompile Include="..\Research\scene\Material\MaterialQuantizer\ColorQuantizer\ColorBitCutter.cpp" />
<ClCompile Include="..\Research\scene\Material\MaterialQuantizer\ColorQuantizer\MaxErrorClusterer.cpp" />
<ClCompile Include="..\Research\scene\Material\MaterialQuantizer\ColorQuantizer\XiangCIELABClusterer.cpp" />
<ClCompile Include="..\Research\scene\Material\MaterialQuantizer\ColorQuantizer\XiangClusterer.cpp" />
<ClCompile Include="..\Research\scene\ObjLoader.cpp" />
<ClCompile Include="..\Research\scene\Octree\HierarchicalColorsOnlyRoot.cpp" />
<ClCompile Include="..\Research\scene\Octree\HierarchicalNode.cpp" />
<ClCompile Include="..\Research\scene\Octree\HierarchicalShiftingColoredRoot.cpp" />
<ClCompile Include="..\Research\scene\Octree\MultiRoot.cpp" />
<ClCompile Include="..\Research\scene\Octree\Node.cpp" />
<ClCompile Include="..\Research\scene\Octree\NodePoolSingleton.cpp" />
<ClCompile Include="..\Research\scene\Octree\Root.cpp" />
<ClCompile Include="..\Research\scene\Octree\UniqueIndexNode.cpp" />
<ClCompile Include="..\Research\scene\PNG.cpp" />
<ClCompile Include="..\Research\scene\PoolBuilder\AdaptivePointerPoolBuilder.cpp" />
<ClCompile Include="..\Research\scene\PoolBuilder\BaseTreePoolBuilder.cpp" />
<ClCompile Include="..\Research\scene\PoolBuilder\StandardPoolBuilder.cpp" />
<ClCompile Include="..\Research\scene\PoolBuilder\VirtualNodePoolBuilder.cpp" />
<ClCompile Include="..\Research\shaders\ShaderLoader.cpp" />
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\Research\core\BitHelper.h" />
<ClInclude Include="..\Research\core\CollectionHelper.h" />
<ClInclude Include="..\Research\core\ColorHelper.h" />
<ClInclude Include="..\Research\core\Hashers.h" />
<ClInclude Include="..\Research\core\IntersectTests.h" />
<ClInclude Include="..\Research\core\MathHelper.h" />
<ClInclude Include="..\Research\core\OctreeBuilder\BaseOctreeBuilder.h" />
<ClInclude Include="..\Research\core\OctreeBuilder\ColorChannelMultiRootOctreeBuilder.h" />
<ClInclude Include="..\Research\core\OctreeBuilder\ColoredOctreeBuilder.h" />
<ClInclude Include="..\Research\core\OctreeBuilder\ColorQuantizer.h" />
<ClInclude Include="..\Research\core\OctreeBuilder\CompressedTextureFactory.h" />
<ClInclude Include="..\Research\core\OctreeBuilder\HierarchicalColoredOctreeBuilder.h" />
<ClInclude Include="..\Research\core\OctreeBuilder\MaterialLibraryMultiRootOctreeBuilder.h" />
<ClInclude Include="..\Research\core\OctreeBuilder\MaterialMultiRootOctreeBuilder.h" />
<ClInclude Include="..\Research\core\OctreeBuilder\MultiBitsMultiRootOctreeBuilder.h" />
<ClInclude Include="..\Research\core\OctreeBuilder\MultiRootOctreeBuilder.h" />
<ClInclude Include="..\Research\core\OctreeBuilder\OctreeBuilder.h" />
<ClInclude Include="..\Research\core\OctreeBuilder\OctreeBuilderStatistics.h" />
<ClInclude Include="..\Research\core\OctreeBuilder\OctreeConverter.h" />
<ClInclude Include="..\Research\core\OctreeBuilder\OctreeLoader.h" />
<ClInclude Include="..\Research\core\OctreeBuilder\PoolBuilderFactory.h" />
<ClInclude Include="..\Research\core\OctreeBuilder\RandomOctreeBuilder.h" />
<ClInclude Include="..\Research\core\OctreeBuilder\SettingsParser.h" />
<ClInclude Include="..\Research\core\OctreeBuilder\StandardOctreeBuilder.h" />
<ClInclude Include="..\Research\core\OctreeBuilder\TreeTypeParser.h" />
<ClInclude Include="..\Research\core\OctreeBuilder\UniqueIndexColoredOctreeBuilder.h" />
<ClInclude Include="..\Research\core\Serializer.h" />
<ClInclude Include="..\Research\core\StringHelper.h" />
<ClInclude Include="..\Research\core\Util\BoolArray.h" />
<ClInclude Include="..\Research\core\Util\ObjectPool.h" />
<ClInclude Include="..\Research\core\Util\Stopwatch.h" />
<ClInclude Include="..\Research\inc\lodepng\lodepng.h" />
<ClInclude Include="..\Research\PropertyLoader.h" />
<ClInclude Include="..\Research\scene\Material\BaseMaterial.h" />
<ClInclude Include="..\Research\scene\Material\BitsMaterial.h" />
<ClInclude Include="..\Research\scene\Material\Block.h" />
<ClInclude Include="..\Research\scene\Material\Color.h" />
<ClInclude Include="..\Research\scene\Material\ColorChannel.h" />
<ClInclude Include="..\Research\scene\Material\MaterialLibrary.h" />
<ClInclude Include="..\Research\scene\Material\MaterialLibraryPointer.h" />
<ClInclude Include="..\Research\scene\Material\MaterialQuantizer\BaseQuantizer.h" />
<ClInclude Include="..\Research\scene\Material\MaterialQuantizer\ColorQuantizer\BaseColorQuantizer.h" />
<ClInclude Include="..\Research\scene\Material\MaterialQuantizer\ColorQuantizer\ColorBitCutter.h" />
<ClInclude Include="..\Research\scene\Material\MaterialQuantizer\ColorQuantizer\MaxErrorClusterer.h" />
<ClInclude Include="..\Research\scene\Material\MaterialQuantizer\ColorQuantizer\XiangCIELABClusterer.h" />
<ClInclude Include="..\Research\scene\Material\MaterialQuantizer\ColorQuantizer\XiangClusterer.h" />
<ClInclude Include="..\Research\scene\ObjLoader.h" />
<ClInclude Include="..\Research\scene\Octree\ChildMask.h" />
<ClInclude Include="..\Research\scene\Octree\ColorChannelMultiRootTree.h" />
<ClInclude Include="..\Research\scene\Octree\ColoredTree.h" />
<ClInclude Include="..\Research\scene\Octree\HierarchicalColorsOnlyRoot.h" />
<ClInclude Include="..\Research\scene\Octree\HierarchicalMaterialMultiRoot.h" />
<ClInclude Include="..\Research\scene\Octree\HierarchicalNode.h" />
<ClInclude Include="..\Research\scene\Octree\HierarchicalRoot.h" />
<ClInclude Include="..\Research\scene\Octree\HierarchicalShiftingColoredRoot.h" />
<ClInclude Include="..\Research\scene\Octree\IAdditionalProperties.h" />
<ClInclude Include="..\Research\scene\Octree\IBlockTexture.h" />
<ClInclude Include="..\Research\scene\Octree\IMaterialTexture.h" />
<ClInclude Include="..\Research\scene\Octree\LeafMaterialMultiRootTree.h" />
<ClInclude Include="..\Research\scene\Octree\LeafMaterialTree.h" />
<ClInclude Include="..\Research\scene\Octree\MaterialLeaf.h" />
<ClInclude Include="..\Research\scene\Octree\MaterialLibraryMultiRootTree.h" />
<ClInclude Include="..\Research\scene\Octree\MaterialNode.h" />
<ClInclude Include="..\Research\scene\Octree\MaterialTree.h" />
<ClInclude Include="..\Research\scene\Octree\MultiRoot.h" />
<ClInclude Include="..\Research\scene\Octree\MultiRootBitsTree.h" />
<ClInclude Include="..\Research\scene\Octree\Node.h" />
<ClInclude Include="..\Research\scene\Octree\NodePoolSingleton.h" />
<ClInclude Include="..\Research\scene\Octree\Root.h" />
<ClInclude Include="..\Research\scene\Octree\UniqueIndexNode.h" />
<ClInclude Include="..\Research\scene\Octree\UniqueIndexRoot.h" />
<ClInclude Include="..\Research\scene\PNG.h" />
<ClInclude Include="..\Research\scene\PoolBuilder\AdaptivePointerPoolBuilder.h" />
<ClInclude Include="..\Research\scene\PoolBuilder\BasePoolBuilder.h" />
<ClInclude Include="..\Research\scene\PoolBuilder\BaseTreePoolBuilder.h" />
<ClInclude Include="..\Research\scene\PoolBuilder\OriginalPoolBuilder.h" />
<ClInclude Include="..\Research\scene\PoolBuilder\StandardPoolBuilder.h" />
<ClInclude Include="..\Research\scene\PoolBuilder\VirtualNodePoolBuilder.h" />
<ClInclude Include="..\Research\scene\Scene.h" />
<ClInclude Include="..\Research\scene\TextureCompressor\BasicTexture.h" />
<ClInclude Include="..\Research\scene\TextureCompressor\BlockCompressedTexture.h" />
<ClInclude Include="..\Research\scene\TextureCompressor\BlockHashers.h" />
<ClInclude Include="..\Research\scene\TextureCompressor\CompressedTexture.h" />
<ClInclude Include="..\Research\scene\TextureCompressor\DagBasedTexture.h" />
<ClInclude Include="..\Research\scene\TextureCompressor\MultiRootBasedTexture.h" />
<ClInclude Include="..\Research\scene\TextureCompressor\PaletteBlockTexture.h" />
<ClInclude Include="..\Research\scene\TextureCompressor\TightlyPackedTexture.h" />
<ClInclude Include="..\Research\shaders\ShaderLoader.h" />
</ItemGroup>
<ItemGroup>
<Text Include="properties.txt" />
<Text Include="shaders\shader_properties.txt" />
</ItemGroup>
<ItemGroup>
<None Include="..\Research\shaders\DepthPeel.frag" />
<None Include="..\Research\shaders\DepthPeel.vert" />
<None Include="..\Research\shaders\RenderTexture.frag" />
<None Include="..\Research\shaders\RenderTexture.vert" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,510 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Core">
<UniqueIdentifier>{3c8b8cfb-4491-485c-ab96-83142c251667}</UniqueIdentifier>
</Filter>
<Filter Include="Shaders">
<UniqueIdentifier>{1202c744-b429-489e-81d3-fa65bd4277d0}</UniqueIdentifier>
</Filter>
<Filter Include="Core\Tree">
<UniqueIdentifier>{6fa9ea14-9539-43e4-bb29-6a354926b492}</UniqueIdentifier>
</Filter>
<Filter Include="Core\OctreeBuilder">
<UniqueIdentifier>{e60bae84-725d-4887-ab75-a99d3ec1f750}</UniqueIdentifier>
</Filter>
<Filter Include="Core\Material">
<UniqueIdentifier>{7b057bda-245e-4f13-b468-0c6292449844}</UniqueIdentifier>
</Filter>
<Filter Include="Core\TextureCompressor">
<UniqueIdentifier>{a987f229-4ea7-4930-8155-6e02985c09d2}</UniqueIdentifier>
</Filter>
<Filter Include="Core\Helpers">
<UniqueIdentifier>{7cf16d36-4ac6-43ad-9ecc-1d5770d97ff6}</UniqueIdentifier>
</Filter>
<Filter Include="Core\Material\MaterialQuantizer">
<UniqueIdentifier>{04637d46-0558-4385-b440-4b4edce6a4a1}</UniqueIdentifier>
</Filter>
<Filter Include="Core\Material\MaterialQuantizer\ColorQuantizer">
<UniqueIdentifier>{86550525-aa17-4e9a-887e-da9c44bb2148}</UniqueIdentifier>
</Filter>
<Filter Include="Core\Util">
<UniqueIdentifier>{6ad777dc-8976-474b-8ffd-c4c7ed369d28}</UniqueIdentifier>
</Filter>
<Filter Include="Core\PoolBuilder">
<UniqueIdentifier>{43e18d10-aa1a-4345-a0e3-767ad568119f}</UniqueIdentifier>
</Filter>
<Filter Include="Core\Voxelizers">
<UniqueIdentifier>{546cba3f-c69e-471c-8bf8-9547d87e13ba}</UniqueIdentifier>
</Filter>
<Filter Include="Core\PVM">
<UniqueIdentifier>{901cc60c-f42c-4e0e-b144-7ba38c8e9044}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\Research\scene\ObjLoader.cpp">
<Filter>Core</Filter>
</ClCompile>
<ClCompile Include="..\Research\scene\PNG.cpp">
<Filter>Core</Filter>
</ClCompile>
<ClCompile Include="main.cpp" />
<ClCompile Include="..\Research\shaders\ShaderLoader.cpp">
<Filter>Shaders</Filter>
</ClCompile>
<ClCompile Include="..\Research\PropertyLoader.cpp">
<Filter>Core</Filter>
</ClCompile>
<ClCompile Include="..\Research\inc\lodepng\lodepng.cpp">
<Filter>Core</Filter>
</ClCompile>
<ClCompile Include="..\Research\core\IntersectTests.cpp">
<Filter>Core</Filter>
</ClCompile>
<ClCompile Include="..\Research\core\ColorHelper.cpp">
<Filter>Core\Helpers</Filter>
</ClCompile>
<ClCompile Include="..\Research\core\StringHelper.cpp">
<Filter>Core\Helpers</Filter>
</ClCompile>
<ClCompile Include="..\Research\scene\Material\MaterialQuantizer\ColorQuantizer\ColorBitCutter.cpp">
<Filter>Core\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClCompile>
<ClCompile Include="..\Research\scene\Material\MaterialQuantizer\ColorQuantizer\MaxErrorClusterer.cpp">
<Filter>Core\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClCompile>
<ClCompile Include="..\Research\scene\Material\MaterialQuantizer\ColorQuantizer\XiangCIELABClusterer.cpp">
<Filter>Core\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClCompile>
<ClCompile Include="..\Research\scene\Material\MaterialQuantizer\ColorQuantizer\XiangClusterer.cpp">
<Filter>Core\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClCompile>
<ClCompile Include="..\Research\scene\Material\Color.cpp">
<Filter>Core\Material</Filter>
</ClCompile>
<ClCompile Include="..\Research\scene\Material\ColorChannel.cpp">
<Filter>Core\Material</Filter>
</ClCompile>
<ClCompile Include="..\Research\scene\Octree\HierarchicalColorsOnlyRoot.cpp">
<Filter>Core\Tree</Filter>
</ClCompile>
<ClCompile Include="..\Research\scene\Octree\HierarchicalNode.cpp">
<Filter>Core\Tree</Filter>
</ClCompile>
<ClCompile Include="..\Research\scene\Octree\HierarchicalShiftingColoredRoot.cpp">
<Filter>Core\Tree</Filter>
</ClCompile>
<ClCompile Include="..\Research\scene\Octree\MultiRoot.cpp">
<Filter>Core\Tree</Filter>
</ClCompile>
<ClCompile Include="..\Research\scene\Octree\Node.cpp">
<Filter>Core\Tree</Filter>
</ClCompile>
<ClCompile Include="..\Research\scene\Octree\Root.cpp">
<Filter>Core\Tree</Filter>
</ClCompile>
<ClCompile Include="..\Research\scene\Octree\UniqueIndexNode.cpp">
<Filter>Core\Tree</Filter>
</ClCompile>
<ClCompile Include="..\Research\core\Util\BoolArray.cpp">
<Filter>Core\Util</Filter>
</ClCompile>
<ClCompile Include="..\Research\core\Util\Stopwatch.cpp">
<Filter>Core\Util</Filter>
</ClCompile>
<ClCompile Include="..\Research\scene\Octree\NodePoolSingleton.cpp">
<Filter>Core\Tree</Filter>
</ClCompile>
<ClCompile Include="..\Research\core\OctreeBuilder\ColoredOctreeBuilder.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="..\Research\core\OctreeBuilder\MaterialLibraryMultiRootOctreeBuilder.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="..\Research\core\OctreeBuilder\MultiRootOctreeBuilder.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="..\Research\core\OctreeBuilder\OctreeBuilder.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="..\Research\core\OctreeBuilder\OctreeConverter.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="..\Research\core\OctreeBuilder\OctreeLoader.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="..\Research\core\OctreeBuilder\RandomOctreeBuilder.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="..\Research\core\OctreeBuilder\SettingsParser.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="..\Research\core\OctreeBuilder\StandardOctreeBuilder.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="..\Research\core\OctreeBuilder\TreeTypeParser.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="..\Research\scene\PoolBuilder\AdaptivePointerPoolBuilder.cpp">
<Filter>Core\PoolBuilder</Filter>
</ClCompile>
<ClCompile Include="..\Research\scene\PoolBuilder\BaseTreePoolBuilder.cpp">
<Filter>Core\PoolBuilder</Filter>
</ClCompile>
<ClCompile Include="..\Research\scene\PoolBuilder\StandardPoolBuilder.cpp">
<Filter>Core\PoolBuilder</Filter>
</ClCompile>
<ClCompile Include="..\Research\scene\PoolBuilder\VirtualNodePoolBuilder.cpp">
<Filter>Core\PoolBuilder</Filter>
</ClCompile>
<ClCompile Include="..\Research\core\OctreeBuilder\UniqueIndexShiftColoredOctreeBuilder.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="..\Research\core\OctreeBuilder\ColorQuantizerFactory.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="..\Research\core\Voxelizer\PVMVoxelizer.cpp">
<Filter>Core\Voxelizers</Filter>
</ClCompile>
<ClCompile Include="..\Research\core\Voxelizer\TriangleMeshVoxelizer.cpp">
<Filter>Core\Voxelizers</Filter>
</ClCompile>
<ClCompile Include="..\Research\inc\pvm\ddsbase.cpp">
<Filter>Core\PVM</Filter>
</ClCompile>
<ClCompile Include="..\Research\core\PathHelper.cpp">
<Filter>Core\Helpers</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\Research\scene\Scene.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="..\Research\inc\lodepng\lodepng.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\ObjLoader.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\PNG.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="..\Research\shaders\ShaderLoader.h">
<Filter>Shaders</Filter>
</ClInclude>
<ClInclude Include="..\Research\PropertyLoader.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\IntersectTests.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\Hashers.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\BitHelper.h">
<Filter>Core\Helpers</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\CollectionHelper.h">
<Filter>Core\Helpers</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\ColorHelper.h">
<Filter>Core\Helpers</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\MathHelper.h">
<Filter>Core\Helpers</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\Serializer.h">
<Filter>Core\Helpers</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\StringHelper.h">
<Filter>Core\Helpers</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Material\MaterialQuantizer\BaseQuantizer.h">
<Filter>Core\Material\MaterialQuantizer</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Material\MaterialQuantizer\ColorQuantizer\BaseColorQuantizer.h">
<Filter>Core\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Material\MaterialQuantizer\ColorQuantizer\ColorBitCutter.h">
<Filter>Core\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Material\MaterialQuantizer\ColorQuantizer\MaxErrorClusterer.h">
<Filter>Core\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Material\MaterialQuantizer\ColorQuantizer\XiangCIELABClusterer.h">
<Filter>Core\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Material\MaterialQuantizer\ColorQuantizer\XiangClusterer.h">
<Filter>Core\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Material\BaseMaterial.h">
<Filter>Core\Material</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Material\BitsMaterial.h">
<Filter>Core\Material</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Material\Block.h">
<Filter>Core\Material</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Material\Color.h">
<Filter>Core\Material</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Material\ColorChannel.h">
<Filter>Core\Material</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Material\MaterialLibrary.h">
<Filter>Core\Material</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Material\MaterialLibraryPointer.h">
<Filter>Core\Material</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\TextureCompressor\BasicTexture.h">
<Filter>Core\TextureCompressor</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\TextureCompressor\BlockCompressedTexture.h">
<Filter>Core\TextureCompressor</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\TextureCompressor\BlockHashers.h">
<Filter>Core\TextureCompressor</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\TextureCompressor\CompressedTexture.h">
<Filter>Core\TextureCompressor</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\TextureCompressor\PaletteBlockTexture.h">
<Filter>Core\TextureCompressor</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\TextureCompressor\TightlyPackedTexture.h">
<Filter>Core\TextureCompressor</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\ChildMask.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\ColorChannelMultiRootTree.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\ColoredTree.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\HierarchicalColorsOnlyRoot.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\HierarchicalMaterialMultiRoot.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\HierarchicalNode.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\HierarchicalRoot.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\HierarchicalShiftingColoredRoot.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\IAdditionalProperties.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\IBlockTexture.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\IMaterialTexture.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\LeafMaterialMultiRootTree.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\LeafMaterialTree.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\MaterialLeaf.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\MaterialLibraryMultiRootTree.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\MaterialNode.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\MaterialTree.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\MultiRoot.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\MultiRootBitsTree.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\Node.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\Root.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\UniqueIndexNode.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\UniqueIndexRoot.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\Util\BoolArray.h">
<Filter>Core\Util</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\Util\ObjectPool.h">
<Filter>Core\Util</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\Util\Stopwatch.h">
<Filter>Core\Util</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\NodePoolSingleton.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\TextureCompressor\MultiRootBasedTexture.h">
<Filter>Core\TextureCompressor</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\TextureCompressor\DagBasedTexture.h">
<Filter>Core\TextureCompressor</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\BaseOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\ColorChannelMultiRootOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\ColoredOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\CompressedTextureFactory.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\MaterialLibraryMultiRootOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\MaterialMultiRootOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\MultiBitsMultiRootOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\MultiRootOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\OctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\OctreeBuilderStatistics.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\OctreeConverter.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\OctreeLoader.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\PoolBuilderFactory.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\RandomOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\SettingsParser.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\StandardOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\TreeTypeParser.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\PoolBuilder\AdaptivePointerPoolBuilder.h">
<Filter>Core\PoolBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\PoolBuilder\BasePoolBuilder.h">
<Filter>Core\PoolBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\PoolBuilder\BaseTreePoolBuilder.h">
<Filter>Core\PoolBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\PoolBuilder\OriginalPoolBuilder.h">
<Filter>Core\PoolBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\PoolBuilder\StandardPoolBuilder.h">
<Filter>Core\PoolBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\PoolBuilder\VirtualNodePoolBuilder.h">
<Filter>Core\PoolBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\UniqueIndexShiftRoot.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\MaterialLibraryUniqueIndexRoot.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\UniqueIndexShiftColoredOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\BaseMaterialOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\HierarchicalMaterialOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\BaseStandardOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Material\ColorAndNormal.h">
<Filter>Core\Material</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Material\SmallNormal.h">
<Filter>Core\Material</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\UniqueIndexMaterialOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\ColorQuantizerFactory.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\ColorAndNormalQuantizerFactory.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Material\MaterialQuantizer\ColorAndNormalQuantizer.h">
<Filter>Core\Material\MaterialQuantizer</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\Voxelizer\PVMVoxelizer.h">
<Filter>Core\Voxelizers</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\Voxelizer\TriangleMeshVoxelizer.h">
<Filter>Core\Voxelizers</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\Voxelizer\VoxelInfo.h">
<Filter>Core\Voxelizers</Filter>
</ClInclude>
<ClInclude Include="..\Research\inc\pvm\codebase.h">
<Filter>Core\PVM</Filter>
</ClInclude>
<ClInclude Include="..\Research\inc\pvm\ddsbase.h">
<Filter>Core\PVM</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\PathHelper.h">
<Filter>Core\Helpers</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Text Include="properties.txt" />
<Text Include="shaders\shader_properties.txt">
<Filter>Shaders</Filter>
</Text>
</ItemGroup>
<ItemGroup>
<None Include="..\Research\shaders\DepthPeel.frag">
<Filter>Shaders</Filter>
</None>
<None Include="..\Research\shaders\DepthPeel.vert">
<Filter>Shaders</Filter>
</None>
<None Include="..\Research\shaders\RenderTexture.frag">
<Filter>Shaders</Filter>
</None>
<None Include="..\Research\shaders\RenderTexture.vert">
<Filter>Shaders</Filter>
</None>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,404 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.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="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release2|Win32">
<Configuration>Release2</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release2|x64">
<Configuration>Release2</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{58AD3A6F-900A-46F6-947E-80D31DF1A60E}</ProjectGuid>
<RootNamespace>OctreeBuilder</RootNamespace>
<WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release2|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release2|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</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 Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<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>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release2|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release2|x64'" Label="PropertySheets">
<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'">
<LibraryPath>$(ProjectDir)\..\Research\lib32;C:\Program Files %28x86%29\Visual Leak Detector\lib\Win32;$(LibraryPath)</LibraryPath>
<IncludePath>C:\Program Files %28x86%29\Visual Leak Detector\include;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LibraryPath>$(ProjectDir)\..\Research\lib64;C:\Program Files %28x86%29\Visual Leak Detector\lib\Win64;$(LibraryPath)</LibraryPath>
<IncludePath>C:\Program Files %28x86%29\Visual Leak Detector\include;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>
</LinkIncremental>
<LibraryPath>$(ProjectDir)\..\Research\lib32;C:\Program Files %28x86%29\Visual Leak Detector\lib\Win32;$(LibraryPath)</LibraryPath>
<IncludePath>C:\Program Files %28x86%29\Visual Leak Detector\include;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release2|Win32'">
<LinkIncremental />
<LibraryPath>$(ProjectDir)\..\Research\lib32;C:\Program Files %28x86%29\Visual Leak Detector\lib\Win32;$(LibraryPath)</LibraryPath>
<IncludePath>C:\Program Files %28x86%29\Visual Leak Detector\include;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental />
<LibraryPath>$(ProjectDir)\..\Research\lib64;C:\Program Files %28x86%29\Visual Leak Detector\lib\Win64;$(LibraryPath)</LibraryPath>
<IncludePath>C:\Program Files %28x86%29\Visual Leak Detector\include;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release2|x64'">
<LinkIncremental />
<LibraryPath>$(ProjectDir)\..\Research\lib64;C:\Program Files %28x86%29\Visual Leak Detector\lib\Win64;$(LibraryPath)</LibraryPath>
<IncludePath>C:\Program Files %28x86%29\Visual Leak Detector\include;$(IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>legacy_stdio_definitions.lib;glfw3.lib;opengl32.lib;glew32.lib;assimp.lib;;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>legacy_stdio_definitions.lib;glfw3.lib;opengl32.lib;glew32.lib;assimp.lib;;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<RuntimeTypeInfo>true</RuntimeTypeInfo>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>legacy_stdio_definitions.lib;glfw3.lib;opengl32.lib;glew32.lib;assimp.lib;;%(AdditionalDependencies)</AdditionalDependencies>
<Profile>true</Profile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release2|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<RuntimeTypeInfo>true</RuntimeTypeInfo>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>legacy_stdio_definitions.lib;glfw3.lib;opengl32.lib;glew32.lib;assimp.lib;;%(AdditionalDependencies)</AdditionalDependencies>
<Profile>true</Profile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>legacy_stdio_definitions.lib;glfw3.lib;opengl32.lib;glew32.lib;assimp.lib;%(AdditionalDependencies);%(AdditionalDependencies)</AdditionalDependencies>
<Profile>true</Profile>
</Link>
<PostBuildEvent>
<Command>xcopy /C /Y "$(SolutionDir)Research\lib64" "$(TargetDir.TrimEnd('\'))"</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release2|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>legacy_stdio_definitions.lib;glfw3.lib;opengl32.lib;glew32.lib;assimp.lib;;%(AdditionalDependencies)</AdditionalDependencies>
<Profile>true</Profile>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\Research\core\ColorHelper.cpp" />
<ClCompile Include="..\Research\core\IntersectTests.cpp" />
<ClCompile Include="..\Research\core\OctreeBuilder\BaseOctreeBuilder.cpp" />
<ClCompile Include="..\Research\core\OctreeBuilder\ColorQuantizerFactory.cpp" />
<ClCompile Include="..\Research\core\OctreeBuilder\MaterialLibraryMultiRootOctreeBuilder.cpp" />
<ClCompile Include="..\Research\core\OctreeBuilder\MultiRootOctreeBuilder.cpp" />
<ClCompile Include="..\Research\core\OctreeBuilder\NormalQuantizerFactory.cpp" />
<ClCompile Include="..\Research\core\OctreeBuilder\OctreeBuilder.cpp" />
<ClCompile Include="..\Research\core\OctreeBuilder\OctreeConverter.cpp" />
<ClCompile Include="..\Research\core\OctreeBuilder\OctreeLoader.cpp" />
<ClCompile Include="..\Research\core\OctreeBuilder\RandomOctreeBuilder.cpp" />
<ClCompile Include="..\Research\core\OctreeBuilder\SettingsParser.cpp" />
<ClCompile Include="..\Research\core\OctreeBuilder\StandardOctreeBuilder.cpp" />
<ClCompile Include="..\Research\core\OctreeBuilder\TreeTypeParser.cpp" />
<ClCompile Include="..\Research\core\OctreeBuilder\UniqueIndexShiftColoredOctreeBuilder.cpp" />
<ClCompile Include="..\Research\core\PathHelper.cpp" />
<ClCompile Include="..\Research\core\StringHelper.cpp" />
<ClCompile Include="..\Research\core\Util\BoolArray.cpp" />
<ClCompile Include="..\Research\core\Util\Stopwatch.cpp" />
<ClCompile Include="..\Research\core\Voxelizer\PVMVoxelizer.cpp" />
<ClCompile Include="..\Research\core\Voxelizer\TriangleMeshVoxelizer.cpp" />
<ClCompile Include="..\Research\inc\lodepng\lodepng.cpp" />
<ClCompile Include="..\Research\inc\pvm\ddsbase.cpp" />
<ClCompile Include="..\Research\PropertyLoader.cpp" />
<ClCompile Include="..\Research\scene\Material\Color.cpp" />
<ClCompile Include="..\Research\scene\Material\ColorChannel.cpp" />
<ClCompile Include="..\Research\scene\Material\MaterialQuantizer\ColorQuantizer\BaseColorQuantizer.cpp" />
<ClCompile Include="..\Research\scene\Material\MaterialQuantizer\ColorQuantizer\ColorBitCutter.cpp" />
<ClCompile Include="..\Research\scene\Material\MaterialQuantizer\ColorQuantizer\MaxErrorClusterer.cpp" />
<ClCompile Include="..\Research\scene\Material\MaterialQuantizer\ColorQuantizer\XiangCIELABClusterer.cpp" />
<ClCompile Include="..\Research\scene\Material\MaterialQuantizer\ColorQuantizer\XiangClusterer.cpp" />
<ClCompile Include="..\Research\scene\Material\MaterialQuantizer\NormalQuantizer.cpp" />
<ClCompile Include="..\Research\scene\ObjLoader.cpp" />
<ClCompile Include="..\Research\scene\Octree\BaseTree.cpp" />
<ClCompile Include="..\Research\scene\Octree\HierarchicalColorsOnlyTree.cpp" />
<ClCompile Include="..\Research\scene\Octree\HierarchicalShiftingColoredTree.cpp" />
<ClCompile Include="..\Research\scene\Octree\Node.cpp" />
<ClCompile Include="..\Research\scene\PNG.cpp" />
<ClCompile Include="..\Research\scene\PoolBuilder\AdaptivePointerPoolBuilder.cpp" />
<ClCompile Include="..\Research\scene\PoolBuilder\BaseTreePoolBuilder.cpp" />
<ClCompile Include="..\Research\scene\PoolBuilder\StandardPoolBuilder.cpp" />
<ClCompile Include="..\Research\scene\PoolBuilder\VirtualNodePoolBuilder.cpp" />
<ClCompile Include="..\Research\shaders\ShaderLoader.cpp" />
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\Research\core\BitHelper.h" />
<ClInclude Include="..\Research\core\CollectionHelper.h" />
<ClInclude Include="..\Research\core\ColorHelper.h" />
<ClInclude Include="..\Research\core\Hashers.h" />
<ClInclude Include="..\Research\core\IntersectTests.h" />
<ClInclude Include="..\Research\core\MathHelper.h" />
<ClInclude Include="..\Research\core\OctreeBuilder\BaseMaterialOctreeBuilder.h" />
<ClInclude Include="..\Research\core\OctreeBuilder\BaseOctreeBuilder.h" />
<ClInclude Include="..\Research\core\OctreeBuilder\BaseStandardOctreeBuilder.h" />
<ClInclude Include="..\Research\core\OctreeBuilder\ColorAndNormalQuantizerFactory.h" />
<ClInclude Include="..\Research\core\OctreeBuilder\ColorAndValueQuantizerFactory.h" />
<ClInclude Include="..\Research\core\OctreeBuilder\ColorChannelMultiRootOctreeBuilder.h" />
<ClInclude Include="..\Research\core\OctreeBuilder\ColorQuantizerFactory.h" />
<ClInclude Include="..\Research\core\OctreeBuilder\CompressedTextureFactory.h" />
<ClInclude Include="..\Research\core\OctreeBuilder\HierarchicalMaterialOctreeBuilder.h" />
<ClInclude Include="..\Research\core\OctreeBuilder\MaterialLibraryMultiRootOctreeBuilder.h" />
<ClInclude Include="..\Research\core\OctreeBuilder\MaterialMultiRootOctreeBuilder.h" />
<ClInclude Include="..\Research\core\OctreeBuilder\MultiBitsMultiRootOctreeBuilder.h" />
<ClInclude Include="..\Research\core\OctreeBuilder\MultiRootOctreeBuilder.h" />
<ClInclude Include="..\Research\core\OctreeBuilder\NormalQuantizerFactory.h" />
<ClInclude Include="..\Research\core\OctreeBuilder\OctreeBuilder.h" />
<ClInclude Include="..\Research\core\OctreeBuilder\OctreeBuilderStatistics.h" />
<ClInclude Include="..\Research\core\OctreeBuilder\OctreeConverter.h" />
<ClInclude Include="..\Research\core\OctreeBuilder\OctreeLoader.h" />
<ClInclude Include="..\Research\core\OctreeBuilder\PoolBuilderFactory.h" />
<ClInclude Include="..\Research\core\OctreeBuilder\RandomOctreeBuilder.h" />
<ClInclude Include="..\Research\core\OctreeBuilder\SettingsParser.h" />
<ClInclude Include="..\Research\core\OctreeBuilder\StandardOctreeBuilder.h" />
<ClInclude Include="..\Research\core\OctreeBuilder\TreeTypeParser.h" />
<ClInclude Include="..\Research\core\OctreeBuilder\UniqueIndexMaterialOctreeBuilder.h" />
<ClInclude Include="..\Research\core\OctreeBuilder\UniqueIndexShiftColoredOctreeBuilder.h" />
<ClInclude Include="..\Research\core\PathHelper.h" />
<ClInclude Include="..\Research\core\Serializer.h" />
<ClInclude Include="..\Research\core\StringHelper.h" />
<ClInclude Include="..\Research\core\Util\BlockVector.h" />
<ClInclude Include="..\Research\core\Util\BoolArray.h" />
<ClInclude Include="..\Research\core\Util\IndexIterator.h" />
<ClInclude Include="..\Research\core\Util\ObjectPool.h" />
<ClInclude Include="..\Research\core\Util\SmallDynamicArray.h" />
<ClInclude Include="..\Research\core\Util\Stopwatch.h" />
<ClInclude Include="..\Research\core\Voxelizer\BaseVoxelizer.h" />
<ClInclude Include="..\Research\core\Voxelizer\PVMVoxelizer.h" />
<ClInclude Include="..\Research\core\Voxelizer\TriangleMeshVoxelizer.h" />
<ClInclude Include="..\Research\core\Voxelizer\VoxelInfo.h" />
<ClInclude Include="..\Research\inc\lodepng\lodepng.h" />
<ClInclude Include="..\Research\inc\pvm\codebase.h" />
<ClInclude Include="..\Research\inc\pvm\ddsbase.h" />
<ClInclude Include="..\Research\PropertyLoader.h" />
<ClInclude Include="..\Research\scene\Material\BaseMaterial.h" />
<ClInclude Include="..\Research\scene\Material\BitsMaterial.h" />
<ClInclude Include="..\Research\scene\Material\Block.h" />
<ClInclude Include="..\Research\scene\Material\Color.h" />
<ClInclude Include="..\Research\scene\Material\ColorAndNormal.h" />
<ClInclude Include="..\Research\scene\Material\ColorAndNormalAndValue.h" />
<ClInclude Include="..\Research\scene\Material\ColorAndOpacity.h" />
<ClInclude Include="..\Research\scene\Material\ColorAndValue.h" />
<ClInclude Include="..\Research\scene\Material\ColorChannel.h" />
<ClInclude Include="..\Research\scene\Material\MaterialLibrary.h" />
<ClInclude Include="..\Research\scene\Material\MaterialLibraryPointer.h" />
<ClInclude Include="..\Research\scene\Material\MaterialPair.h" />
<ClInclude Include="..\Research\scene\Material\MaterialQuantizer\BaseQuantizer.h" />
<ClInclude Include="..\Research\scene\Material\MaterialQuantizer\ColorAndNormalQuantizer.h" />
<ClInclude Include="..\Research\scene\Material\MaterialQuantizer\ColorQuantizer\BaseColorQuantizer.h" />
<ClInclude Include="..\Research\scene\Material\MaterialQuantizer\ColorQuantizer\ColorBitCutter.h" />
<ClInclude Include="..\Research\scene\Material\MaterialQuantizer\ColorQuantizer\MaxErrorClusterer.h" />
<ClInclude Include="..\Research\scene\Material\MaterialQuantizer\ColorQuantizer\XiangCIELABClusterer.h" />
<ClInclude Include="..\Research\scene\Material\MaterialQuantizer\ColorQuantizer\XiangClusterer.h" />
<ClInclude Include="..\Research\scene\Material\MaterialQuantizer\NormalQuantizer.h" />
<ClInclude Include="..\Research\scene\Material\SmallNormal.h" />
<ClInclude Include="..\Research\scene\ObjLoader.h" />
<ClInclude Include="..\Research\scene\Octree\BaseTree.h" />
<ClInclude Include="..\Research\scene\Octree\ChildMask.h" />
<ClInclude Include="..\Research\scene\Octree\EdgeMaterialNode.h" />
<ClInclude Include="..\Research\scene\Octree\HierarchicalColorsOnlyTree.h" />
<ClInclude Include="..\Research\scene\Octree\HierarchicalMaterialMultiRoot.h" />
<ClInclude Include="..\Research\scene\Octree\HierarchicalShiftingColoredTree.h" />
<ClInclude Include="..\Research\scene\Octree\IAdditionalProperties.h" />
<ClInclude Include="..\Research\scene\Octree\IBlockTexture.h" />
<ClInclude Include="..\Research\scene\Octree\IMaterialTexture.h" />
<ClInclude Include="..\Research\scene\Octree\LeafMaterialMultiRootTree.h" />
<ClInclude Include="..\Research\scene\Octree\MaterialLibraryMultiRootTree.h" />
<ClInclude Include="..\Research\scene\Octree\MaterialLibraryTree.h" />
<ClInclude Include="..\Research\scene\Octree\MaterialLibraryUniqueIndexTree.h" />
<ClInclude Include="..\Research\scene\Octree\MaterialNode.h" />
<ClInclude Include="..\Research\scene\Octree\MaterialTree.h" />
<ClInclude Include="..\Research\scene\Octree\MultiRootTree.h" />
<ClInclude Include="..\Research\scene\Octree\Node.h" />
<ClInclude Include="..\Research\scene\Octree\NodeReplacementFinder.h" />
<ClInclude Include="..\Research\scene\Octree\Tree.h" />
<ClInclude Include="..\Research\scene\Octree\UniqueIndexShiftTree.h" />
<ClInclude Include="..\Research\scene\Octree\UniqueIndexTree.h" />
<ClInclude Include="..\Research\scene\PNG.h" />
<ClInclude Include="..\Research\scene\PoolBuilder\AdaptivePointerPoolBuilder.h" />
<ClInclude Include="..\Research\scene\PoolBuilder\BasePoolBuilder.h" />
<ClInclude Include="..\Research\scene\PoolBuilder\BaseTreePoolBuilder.h" />
<ClInclude Include="..\Research\scene\PoolBuilder\OriginalPoolBuilder.h" />
<ClInclude Include="..\Research\scene\PoolBuilder\StandardPoolBuilder.h" />
<ClInclude Include="..\Research\scene\PoolBuilder\VirtualNodePoolBuilder.h" />
<ClInclude Include="..\Research\scene\Scene.h" />
<ClInclude Include="..\Research\scene\TextureCompressor\BasicTexture.h" />
<ClInclude Include="..\Research\scene\TextureCompressor\BlockCompressedTexture.h" />
<ClInclude Include="..\Research\scene\TextureCompressor\BlockHashers.h" />
<ClInclude Include="..\Research\scene\TextureCompressor\CompressedTexture.h" />
<ClInclude Include="..\Research\scene\TextureCompressor\DagBasedTexture.h" />
<ClInclude Include="..\Research\scene\TextureCompressor\MultiRootBasedTexture.h" />
<ClInclude Include="..\Research\scene\TextureCompressor\PaletteBlockTexture.h" />
<ClInclude Include="..\Research\scene\TextureCompressor\TightlyPackedTexture.h" />
<ClInclude Include="..\Research\shaders\ShaderLoader.h" />
</ItemGroup>
<ItemGroup>
<Text Include="properties.txt" />
<Text Include="shaders\shader_properties.txt" />
</ItemGroup>
<ItemGroup>
<None Include="..\Research\shaders\DepthPeel.frag" />
<None Include="..\Research\shaders\DepthPeel.vert" />
<None Include="..\Research\shaders\RenderTexture.frag" />
<None Include="..\Research\shaders\RenderTexture.vert" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,522 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Core">
<UniqueIdentifier>{3c8b8cfb-4491-485c-ab96-83142c251667}</UniqueIdentifier>
</Filter>
<Filter Include="Shaders">
<UniqueIdentifier>{1202c744-b429-489e-81d3-fa65bd4277d0}</UniqueIdentifier>
</Filter>
<Filter Include="Core\Tree">
<UniqueIdentifier>{6fa9ea14-9539-43e4-bb29-6a354926b492}</UniqueIdentifier>
</Filter>
<Filter Include="Core\OctreeBuilder">
<UniqueIdentifier>{e60bae84-725d-4887-ab75-a99d3ec1f750}</UniqueIdentifier>
</Filter>
<Filter Include="Core\Material">
<UniqueIdentifier>{7b057bda-245e-4f13-b468-0c6292449844}</UniqueIdentifier>
</Filter>
<Filter Include="Core\TextureCompressor">
<UniqueIdentifier>{a987f229-4ea7-4930-8155-6e02985c09d2}</UniqueIdentifier>
</Filter>
<Filter Include="Core\Helpers">
<UniqueIdentifier>{7cf16d36-4ac6-43ad-9ecc-1d5770d97ff6}</UniqueIdentifier>
</Filter>
<Filter Include="Core\Material\MaterialQuantizer">
<UniqueIdentifier>{04637d46-0558-4385-b440-4b4edce6a4a1}</UniqueIdentifier>
</Filter>
<Filter Include="Core\Material\MaterialQuantizer\ColorQuantizer">
<UniqueIdentifier>{86550525-aa17-4e9a-887e-da9c44bb2148}</UniqueIdentifier>
</Filter>
<Filter Include="Core\Util">
<UniqueIdentifier>{6ad777dc-8976-474b-8ffd-c4c7ed369d28}</UniqueIdentifier>
</Filter>
<Filter Include="Core\PoolBuilder">
<UniqueIdentifier>{43e18d10-aa1a-4345-a0e3-767ad568119f}</UniqueIdentifier>
</Filter>
<Filter Include="Core\Voxelizers">
<UniqueIdentifier>{546cba3f-c69e-471c-8bf8-9547d87e13ba}</UniqueIdentifier>
</Filter>
<Filter Include="Core\PVM">
<UniqueIdentifier>{901cc60c-f42c-4e0e-b144-7ba38c8e9044}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\Research\scene\ObjLoader.cpp">
<Filter>Core</Filter>
</ClCompile>
<ClCompile Include="..\Research\scene\PNG.cpp">
<Filter>Core</Filter>
</ClCompile>
<ClCompile Include="main.cpp" />
<ClCompile Include="..\Research\shaders\ShaderLoader.cpp">
<Filter>Shaders</Filter>
</ClCompile>
<ClCompile Include="..\Research\PropertyLoader.cpp">
<Filter>Core</Filter>
</ClCompile>
<ClCompile Include="..\Research\inc\lodepng\lodepng.cpp">
<Filter>Core</Filter>
</ClCompile>
<ClCompile Include="..\Research\core\IntersectTests.cpp">
<Filter>Core</Filter>
</ClCompile>
<ClCompile Include="..\Research\core\ColorHelper.cpp">
<Filter>Core\Helpers</Filter>
</ClCompile>
<ClCompile Include="..\Research\core\StringHelper.cpp">
<Filter>Core\Helpers</Filter>
</ClCompile>
<ClCompile Include="..\Research\scene\Material\MaterialQuantizer\ColorQuantizer\ColorBitCutter.cpp">
<Filter>Core\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClCompile>
<ClCompile Include="..\Research\scene\Material\MaterialQuantizer\ColorQuantizer\MaxErrorClusterer.cpp">
<Filter>Core\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClCompile>
<ClCompile Include="..\Research\scene\Material\MaterialQuantizer\ColorQuantizer\XiangCIELABClusterer.cpp">
<Filter>Core\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClCompile>
<ClCompile Include="..\Research\scene\Material\MaterialQuantizer\ColorQuantizer\XiangClusterer.cpp">
<Filter>Core\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClCompile>
<ClCompile Include="..\Research\scene\Material\Color.cpp">
<Filter>Core\Material</Filter>
</ClCompile>
<ClCompile Include="..\Research\scene\Material\ColorChannel.cpp">
<Filter>Core\Material</Filter>
</ClCompile>
<ClCompile Include="..\Research\core\Util\BoolArray.cpp">
<Filter>Core\Util</Filter>
</ClCompile>
<ClCompile Include="..\Research\core\Util\Stopwatch.cpp">
<Filter>Core\Util</Filter>
</ClCompile>
<ClCompile Include="..\Research\core\OctreeBuilder\MaterialLibraryMultiRootOctreeBuilder.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="..\Research\core\OctreeBuilder\MultiRootOctreeBuilder.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="..\Research\core\OctreeBuilder\OctreeBuilder.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="..\Research\core\OctreeBuilder\OctreeConverter.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="..\Research\core\OctreeBuilder\OctreeLoader.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="..\Research\core\OctreeBuilder\RandomOctreeBuilder.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="..\Research\core\OctreeBuilder\SettingsParser.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="..\Research\core\OctreeBuilder\StandardOctreeBuilder.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="..\Research\core\OctreeBuilder\TreeTypeParser.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="..\Research\scene\PoolBuilder\AdaptivePointerPoolBuilder.cpp">
<Filter>Core\PoolBuilder</Filter>
</ClCompile>
<ClCompile Include="..\Research\scene\PoolBuilder\BaseTreePoolBuilder.cpp">
<Filter>Core\PoolBuilder</Filter>
</ClCompile>
<ClCompile Include="..\Research\scene\PoolBuilder\StandardPoolBuilder.cpp">
<Filter>Core\PoolBuilder</Filter>
</ClCompile>
<ClCompile Include="..\Research\scene\PoolBuilder\VirtualNodePoolBuilder.cpp">
<Filter>Core\PoolBuilder</Filter>
</ClCompile>
<ClCompile Include="..\Research\core\OctreeBuilder\UniqueIndexShiftColoredOctreeBuilder.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="..\Research\core\OctreeBuilder\ColorQuantizerFactory.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="..\Research\core\Voxelizer\PVMVoxelizer.cpp">
<Filter>Core\Voxelizers</Filter>
</ClCompile>
<ClCompile Include="..\Research\core\Voxelizer\TriangleMeshVoxelizer.cpp">
<Filter>Core\Voxelizers</Filter>
</ClCompile>
<ClCompile Include="..\Research\inc\pvm\ddsbase.cpp">
<Filter>Core\PVM</Filter>
</ClCompile>
<ClCompile Include="..\Research\core\PathHelper.cpp">
<Filter>Core\Helpers</Filter>
</ClCompile>
<ClCompile Include="..\Research\scene\Octree\BaseTree.cpp">
<Filter>Core\Tree</Filter>
</ClCompile>
<ClCompile Include="..\Research\scene\Octree\HierarchicalColorsOnlyTree.cpp">
<Filter>Core\Tree</Filter>
</ClCompile>
<ClCompile Include="..\Research\scene\Octree\HierarchicalShiftingColoredTree.cpp">
<Filter>Core\Tree</Filter>
</ClCompile>
<ClCompile Include="..\Research\scene\Octree\Node.cpp">
<Filter>Core\Tree</Filter>
</ClCompile>
<ClCompile Include="..\Research\core\OctreeBuilder\BaseOctreeBuilder.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="..\Research\scene\Material\MaterialQuantizer\ColorQuantizer\BaseColorQuantizer.cpp">
<Filter>Core\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClCompile>
<ClCompile Include="..\Research\scene\Material\MaterialQuantizer\NormalQuantizer.cpp">
<Filter>Core\Material\MaterialQuantizer</Filter>
</ClCompile>
<ClCompile Include="..\Research\core\OctreeBuilder\NormalQuantizerFactory.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\Research\scene\Scene.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="..\Research\inc\lodepng\lodepng.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\ObjLoader.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\PNG.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="..\Research\shaders\ShaderLoader.h">
<Filter>Shaders</Filter>
</ClInclude>
<ClInclude Include="..\Research\PropertyLoader.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\IntersectTests.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\Hashers.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\BitHelper.h">
<Filter>Core\Helpers</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\CollectionHelper.h">
<Filter>Core\Helpers</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\ColorHelper.h">
<Filter>Core\Helpers</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\MathHelper.h">
<Filter>Core\Helpers</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\Serializer.h">
<Filter>Core\Helpers</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\StringHelper.h">
<Filter>Core\Helpers</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Material\MaterialQuantizer\BaseQuantizer.h">
<Filter>Core\Material\MaterialQuantizer</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Material\MaterialQuantizer\ColorQuantizer\BaseColorQuantizer.h">
<Filter>Core\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Material\MaterialQuantizer\ColorQuantizer\ColorBitCutter.h">
<Filter>Core\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Material\MaterialQuantizer\ColorQuantizer\MaxErrorClusterer.h">
<Filter>Core\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Material\MaterialQuantizer\ColorQuantizer\XiangCIELABClusterer.h">
<Filter>Core\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Material\MaterialQuantizer\ColorQuantizer\XiangClusterer.h">
<Filter>Core\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Material\BaseMaterial.h">
<Filter>Core\Material</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Material\BitsMaterial.h">
<Filter>Core\Material</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Material\Block.h">
<Filter>Core\Material</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Material\Color.h">
<Filter>Core\Material</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Material\ColorChannel.h">
<Filter>Core\Material</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Material\MaterialLibrary.h">
<Filter>Core\Material</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Material\MaterialLibraryPointer.h">
<Filter>Core\Material</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\TextureCompressor\BasicTexture.h">
<Filter>Core\TextureCompressor</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\TextureCompressor\BlockCompressedTexture.h">
<Filter>Core\TextureCompressor</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\TextureCompressor\BlockHashers.h">
<Filter>Core\TextureCompressor</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\TextureCompressor\CompressedTexture.h">
<Filter>Core\TextureCompressor</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\TextureCompressor\PaletteBlockTexture.h">
<Filter>Core\TextureCompressor</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\TextureCompressor\TightlyPackedTexture.h">
<Filter>Core\TextureCompressor</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\Util\BoolArray.h">
<Filter>Core\Util</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\Util\ObjectPool.h">
<Filter>Core\Util</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\Util\Stopwatch.h">
<Filter>Core\Util</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\TextureCompressor\MultiRootBasedTexture.h">
<Filter>Core\TextureCompressor</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\TextureCompressor\DagBasedTexture.h">
<Filter>Core\TextureCompressor</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\BaseOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\ColorChannelMultiRootOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\CompressedTextureFactory.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\MaterialLibraryMultiRootOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\MaterialMultiRootOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\MultiBitsMultiRootOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\MultiRootOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\OctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\OctreeBuilderStatistics.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\OctreeConverter.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\OctreeLoader.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\PoolBuilderFactory.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\RandomOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\SettingsParser.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\StandardOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\TreeTypeParser.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\PoolBuilder\AdaptivePointerPoolBuilder.h">
<Filter>Core\PoolBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\PoolBuilder\BasePoolBuilder.h">
<Filter>Core\PoolBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\PoolBuilder\BaseTreePoolBuilder.h">
<Filter>Core\PoolBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\PoolBuilder\OriginalPoolBuilder.h">
<Filter>Core\PoolBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\PoolBuilder\StandardPoolBuilder.h">
<Filter>Core\PoolBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\PoolBuilder\VirtualNodePoolBuilder.h">
<Filter>Core\PoolBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\UniqueIndexShiftColoredOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\BaseMaterialOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\HierarchicalMaterialOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\BaseStandardOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Material\ColorAndNormal.h">
<Filter>Core\Material</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Material\SmallNormal.h">
<Filter>Core\Material</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\UniqueIndexMaterialOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\ColorQuantizerFactory.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\ColorAndNormalQuantizerFactory.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Material\MaterialQuantizer\ColorAndNormalQuantizer.h">
<Filter>Core\Material\MaterialQuantizer</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\Voxelizer\PVMVoxelizer.h">
<Filter>Core\Voxelizers</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\Voxelizer\TriangleMeshVoxelizer.h">
<Filter>Core\Voxelizers</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\Voxelizer\VoxelInfo.h">
<Filter>Core\Voxelizers</Filter>
</ClInclude>
<ClInclude Include="..\Research\inc\pvm\codebase.h">
<Filter>Core\PVM</Filter>
</ClInclude>
<ClInclude Include="..\Research\inc\pvm\ddsbase.h">
<Filter>Core\PVM</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\PathHelper.h">
<Filter>Core\Helpers</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\ColorAndValueQuantizerFactory.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Material\ColorAndOpacity.h">
<Filter>Core\Material</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Material\ColorAndValue.h">
<Filter>Core\Material</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Material\MaterialPair.h">
<Filter>Core\Material</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Material\ColorAndNormalAndValue.h">
<Filter>Core\Material</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\Util\SmallDynamicArray.h">
<Filter>Core\Util</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\Voxelizer\BaseVoxelizer.h">
<Filter>Core\Voxelizers</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\BaseTree.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\ChildMask.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\EdgeMaterialNode.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\HierarchicalColorsOnlyTree.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\HierarchicalMaterialMultiRoot.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\HierarchicalShiftingColoredTree.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\IAdditionalProperties.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\IBlockTexture.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\IMaterialTexture.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\LeafMaterialMultiRootTree.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\MaterialLibraryMultiRootTree.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\MaterialLibraryTree.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\MaterialLibraryUniqueIndexTree.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\MaterialNode.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\MaterialTree.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\MultiRootTree.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\Node.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\NodeReplacementFinder.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\Tree.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\UniqueIndexShiftTree.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Octree\UniqueIndexTree.h">
<Filter>Core\Tree</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\Util\BlockVector.h">
<Filter>Core\Util</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\Util\IndexIterator.h">
<Filter>Core\Util</Filter>
</ClInclude>
<ClInclude Include="..\Research\scene\Material\MaterialQuantizer\NormalQuantizer.h">
<Filter>Core\Material\MaterialQuantizer</Filter>
</ClInclude>
<ClInclude Include="..\Research\core\OctreeBuilder\NormalQuantizerFactory.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Text Include="properties.txt" />
<Text Include="shaders\shader_properties.txt">
<Filter>Shaders</Filter>
</Text>
</ItemGroup>
<ItemGroup>
<None Include="..\Research\shaders\DepthPeel.frag">
<Filter>Shaders</Filter>
</None>
<None Include="..\Research\shaders\DepthPeel.vert">
<Filter>Shaders</Filter>
</None>
<None Include="..\Research\shaders\RenderTexture.frag">
<Filter>Shaders</Filter>
</None>
<None Include="..\Research\shaders\RenderTexture.vert">
<Filter>Shaders</Filter>
</None>
</ItemGroup>
</Project>

View File

@@ -0,0 +1 @@
start "OctreeBuilder" %~dp0\..\x64\Release\OctreeBuilder.exe

282
OctreeBuilder/main.cpp Normal file
View File

@@ -0,0 +1,282 @@
#include <iostream>
#include "../Research/core/OctreeBuilder/OctreeBuilder.h"
#include "../Research/core/OctreeBuilder/OctreeLoader.h"
#include "../Research/core/OctreeBuilder/OctreeConverter.h"
#include "../Research/PropertyLoader.h"
#include "../Research/scene/Octree/BaseTree.h"
#include "../Research/core/Util/Stopwatch.h"
#include <fstream>
#ifdef _WIN32
#include <windows.h>
//#ifdef _DEBUG
//#include <vld.h>
//#endif
// Make sure NVidia GPU is used on laptops with Nvidia optimus
extern "C" {
_declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
}
#endif
int main() {
// Create the nodepool (OctreeBuilder will use it automatically when available)
//NodePoolSingleton::Create();
PropertyLoader::Create();
PropertyLoader* propertyLoader = PropertyLoader::Instance();
unsigned startLevel = propertyLoader->GetIntProperty("start_level");
unsigned endLevel = propertyLoader->GetIntProperty("end_level");
bool useCache = propertyLoader->GetBoolProperty("octreebuilder_usecache");
bool tryConvert = propertyLoader->GetBoolProperty("octreebuilder_tryconvert");
bool onlyCache = propertyLoader->GetBoolProperty("octreebuilder_onlycache");
bool writeStats = propertyLoader->GetBoolProperty("octreebuilder_writestats");
//std::vector<OctreeBuilderStatistics> stats;
std::string csvFilename = propertyLoader->GetProperty("stats_file");
csvFilename.append("_stats.csv");
std::vector<std::string> types = propertyLoader->GetListProperty("tree_type");
std::vector<std::string> poolTypes = propertyLoader->GetListProperty("pool_type");
std::vector<std::string> sceneFilenames = propertyLoader->GetListProperty("scene_file");
std::vector<std::string> dagFilenames = propertyLoader->GetListProperty("dag_file");
assert(dagFilenames.size() == sceneFilenames.size());
std::vector<std::pair<std::string, std::string>> scenes(dagFilenames.size());
for (size_t i = 0; i < dagFilenames.size(); i++)
scenes[i] = std::make_pair(sceneFilenames[i], dagFilenames[i]);
// std::string csvFilename = propertyLoader->GetProperty("dag_file");
// csvFilename.append("_stats.csv");
// std::vector<std::string> types = {
// //"s",
// //"c",
// //"m1",
// //"m2",
// //"m3",
// //"m4",
// //"m5",
// //"m6",
// //"m7",
// //"m8",
// //"mcc"
// //"m8b2",
// //"m8b4",
// //"m7b2",
// //"m7b3",
// //"c32",
// //"c64",
// //"c128",
// //"c256",
// //"c512",
// //"c1024",
// //"c2048",
// //"hc"
// //"hcde2.7",
// //"hcde5.4",
// //"hclab1024",
// //"hclab512",
// //"u4c",
// //"u8c",
// //"u16c",
// //"u32c",
// //"u4cde2.7",
// //"u8cde2.7",
// //"u16cde2.7",
// //"u32cde2.7",
// //"u4cde1.3",
// //"u8cde1.3",
// //"u16cde1.3",
// //"u32cde1.3",
// //"utcde2.7",
// //"utcde1.3".
// //"blc",
// //"clab4096",
// //"hclab4096",
// //"upc",
// "hc",
//// "upclab256",
// //"hclab256",
//// "upclab1024",
// //"hclab1024",
//// "upclab4096",
// //"hclab4096",
// };
//
// std::vector<std::string> poolTypes = {
// "s",
// //"o",
// //"al",
// };
//
// std::vector<std::pair<std::string, std::string>> scenes =
// {
//// std::make_pair("../Research/data/arena.ply", "../Research/data/arena"),
//// std::make_pair("../Research/data/city.obj", "../Research/data/city"),
//// std::make_pair("../Research/data/EpicCitadel/EpicCitadel.obj", "../Research/data/citadel"),
//// std::make_pair("../Research/data/SanMiguel/san-miguel.obj", "../Research/data/sanmiguel"),
// std::make_pair("../Research/data/statue.ply", "../Research/data/statue"),
// //std::make_pair("../Research/data/Sponza/sponza.obj", "../Research/data/sponza"),
// };
// std::vector<unsigned8> maxDepthPerScene =
// {
// 17, 17, 17, 17, 17, 17
// //17, 15,/* 14, 12,*/ 15
// };
std::ofstream output;
output.open(csvFilename);
output << "scene,type,pooltype,levels,buildTime,octreenodes,dagNodes,pointerCount,compression,gpuMemory,gpuMemoryMB,mainTreeGpuMemory,mainTreeGpuMemoryMB,additionalGpuMemory,additionalGpuMemoryMB,";
for (unsigned lvl = 0; lvl <= endLevel; lvl++)
output << "octreeNodesLevel" << lvl << ",";
for (unsigned lvl = 0; lvl <= endLevel; lvl++)
{
output << "dagNodesLevel" << lvl;
if (lvl < endLevel) output << ",";
else output << "\n";
}
bool builderCreated = false;
struct BuildOption
{
std::string type;
unsigned8 level;
std::string sceneFile;
std::string dagFile;
std::string sceneName;
};
std::vector<BuildOption> failed;
for (unsigned8 level = startLevel; level <= endLevel; level++)
{
for (auto type : types)
{
for (size_t sceneId = 0; sceneId < scenes.size(); sceneId++)
{
for (size_t count = 0; count < 1; count++) {
auto scene = scenes[sceneId];
std::string sceneName = scene.second;
const size_t last_slash_idx = sceneName.find_last_of("\\/");
if (std::string::npos != last_slash_idx) {
sceneName.erase(0, last_slash_idx + 1);
}
printf("Building scene %s, type %s up to %u levels\n", sceneName.c_str(), type.c_str(), level);
OctreeBuilderStatistics stat(level);
bool cacheVerified = false;
bool justBuild = false;
if (!onlyCache)
{
if (useCache)
cacheVerified = OctreeLoader::VerifyCache(type, level, scene.second);
if (!cacheVerified && useCache && tryConvert)
cacheVerified = OctreeConverter::ConvertTo(type, level, scene.second, true);
if (!useCache || !cacheVerified) {
if (!builderCreated) {
OctreeBuilder::Create();
builderCreated = true;
}
OctreeBuilder::SetTreeType(type);
stat = OctreeBuilder::BuildOctree(level, scene.first, scene.second);
justBuild = true;
}
}
// Verify the tree is build correctly (and saved)
if (!cacheVerified) cacheVerified = OctreeLoader::VerifyCache(type, level, scene.second);
// If the file is valid and we're instructed to build pools, build the pool and write stats
if (cacheVerified) {
if (writeStats)
{
//{
// unsigned poolSize, materialTextureSize, materialNodePoolTextureSize, blockPointerPoolSize, blockPoolSize;
// unsigned8 blockPointerPoolChannelsPerPixel, blockPoolChannelsPerPixel;
// std::vector<unsigned32> blockPointerPool;
// std::vector<unsigned8> nodePool, materialNodePool;
// std::vector<unsigned char> materialTexture, blockPool;
// std::map<std::string, std::string> additionalProperties;
// OctreeLoader::GetPool(type, level, scene.second, false, nodePool, poolSize, materialTexture, materialTextureSize, materialNodePool, materialNodePoolTextureSize, blockPointerPool, blockPointerPoolSize, blockPointerPoolChannelsPerPixel, blockPool, blockPoolSize, blockPoolChannelsPerPixel, additionalProperties, true);
//}
BaseTree *tree = OctreeLoader::ReadCache(type, level, scene.second, false);
size_t pointerCount = tree->GetPointerCount();
for (std::string poolType : poolTypes) {
double mbDivider = 1. / ((double)1024 * 1024);
size_t gpuMem = OctreeLoader::GetGPUMemoryRequirements(type, poolType, tree);
double gpuMemMB = (double)(gpuMem) * mbDivider;
size_t mainTreeGpuMem = OctreeLoader::GetMainTreeGPUMemoryRequirements(type, poolType, tree);
double mainTreeGpuMemMB = ((double)mainTreeGpuMem) * mbDivider;
size_t additionalGpuMem = gpuMem - mainTreeGpuMem;
double additionalGpuMemMB = ((double)additionalGpuMem) * mbDivider;
if (useCache && !justBuild) {
stat.type = type;
stat.octreeNodesPerLevel = tree->GetOctreeNodesPerLevel();
stat.dagNodesPerLevel = tree->GetNodesPerLevel();
}
// Write the stats to a CSV file
output << sceneName << "," << stat.type << "," << poolType << "," << (size_t)level <<
"," << stat.totalTime << "," << stat.GetOctreeNodeCount() <<
"," << stat.GetDAGNodeCount() << "," << pointerCount << "," << stat.GetCompression() << "," << gpuMem << "," <<
gpuMemMB << "," << mainTreeGpuMem << "," << mainTreeGpuMemMB << "," << additionalGpuMem << "," << additionalGpuMemMB << ",";
for (unsigned lvl = 0; lvl <= endLevel; lvl++) {
if (lvl <= level) output << stat.octreeNodesPerLevel[lvl];
else output << "0";
output << ",";
}
for (unsigned lvl = 0; lvl <= endLevel; lvl++) {
if (lvl < level) output << stat.dagNodesPerLevel[lvl];
else output << "0";
if (lvl < endLevel) output << ",";
else output << "\n";
}
}
delete tree;
}
}
else
{
printf("Failed...\n");
BuildOption f;
f.type = type;
f.level = level;
f.sceneFile = scene.first;
f.dagFile = scene.second;
f.sceneName = sceneName;
failed.push_back(f);
}
output.flush();
}
}
}
}
output.close();
if (!useCache)
OctreeBuilder::Destroy();
if (!failed.empty())
{
printf("Construction failed for the following options:\n");
for (BuildOption f : failed)
printf(" - %s, type %s, %u levels\n", f.sceneName.c_str(), f.type.c_str(), f.level);
}
//NodePoolSingleton::Destroy();
#ifdef _WIN32
system("pause");
#endif
return 0;
}

View File

@@ -0,0 +1,92 @@
anti_aliasing 0
opengl_version_major 3
opengl_version_minor 3
octreebuilder_debug_width 1024
octreebuilder_debug_height 1024
octreebuilder_manual 0
octreebuilder_renderscene 0
octreebuilder_verbose 1
octreebuilder_interpolate_colors 1
octreebuilder_usecache 1
octreebuilder_forcerebuild 0
octreebuilder_tryconvert 0
octreebuilder_onlycache 0
octreebuilder_writestats 1
octreebuilder_max_single_pass_layers 12
octreebuilder_missing_material ../Research/data/SanMiguel/Maps/cut59Lb.png
octreebuilder_poolsize 20000000
window_name OctreeBuilder
verbose 1
start_level 12
end_level 12
stats_file ../Research/data/no_offset_compression
#tree_type0 blclab256
#tree_type1 blclab1024
#tree_type0 blclab4096
#tree_type1 blc
#tree_type0 s
#tree_type1 hc
#tree_type2 upc
#tree_type3 hclab256
#tree_type4 hclab1024
#tree_type5 hclab4096
#tree_type6 upclab256
#tree_type7 upclab1024
#tree_type8 upclab4096
#tree_type0 utclab256
#tree_type1 utclab1024
#tree_type2 utclab4096
#tree_type3 utc
#tree_type0 u1lodpclab4096
#tree_type0 upcnrlab4096
#tree_type0 upn
#tree_type1 hn
#tree_type0 upc
#tree_type1 upclab16384
#tree_type0 s
#tree_type0 hclab4096
#tree_type1 hc
#tree_type0 hclab4096
#tree_type1 upclab4096
#tree_type2 blclab4096
#tree_type3 utclab4096
#tree_type0 umclab4096
#tree_type0 ut8clab4096
#tree_type0 upclab16384
#tree_type1 hclab16384
tree_type0 upclab4096
pool_type0 s
#pool_type1 al2
#pool_type2 v
#pool_type3 o
scene_file0 ../Research/data/EpicCitadel/EpicCitadel.obj
dag_file0 F:/Master Thesis/citadel
#scene_file1 ../Research/data/city.obj
#dag_file1 F:/Master Thesis/city
#scene_file2 ../Research/data/SanMiguel/san-miguel.obj
#dag_file2 F:/Master Thesis/sanmiguel
#scene_file3 ../Research/data/arena.ply
#dag_file3 F:/Master Thesis/arena
#scene_file0 ../Research/data/arena.ply
#dag_file0 ../Research/data/arena
#scene_file0 ../Research/data/EpicCitadel/EpicCitadel.obj
#dag_file0 E:/Master Thesis/citadel
#scene_file0 ../Research/data/statue.ply
#dag_file0 ../Research/data/statue
#scene_file0 ../Research/data/SanMiguel/san-miguel.obj
#dag_file0 F:/Master Thesis/sanmiguel
#scene_file0 ../Research/data/city.obj
#dag_file0 ../Research/data/city
#scene_file0 ../Research/data/city_night.obj
#dag_file0 ../Research/data/city-night
#scene_file1 ../Research/data/statuette.ply
#dag_file1 ../Research/data/16N/statuette

View File

@@ -0,0 +1,13 @@
shader_vertexPosition 0
shader_vertexUV 1
shader_vertexNormal 2
shader_vertexColor 3
shader_MVP 0
shader_width 1
shader_height 2
shader_angle 3
shader_aspect 4
shader_cameraPosition 6
shader_max_level 15

1
README.md Normal file
View File

@@ -0,0 +1 @@
CDAG

54
Research.sln Normal file
View File

@@ -0,0 +1,54 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.23107.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Research", "Research\Research.vcxproj", "{22A4991F-1B7C-463F-BB36-AA539CA28F4A}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OctreeBuilder", "OctreeBuilder\OctreeBuilder.vcxproj", "{58AD3A6F-900A-46F6-947E-80D31DF1A60E}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{22E8F3DE-3666-473D-84AE-5717C0A87CD0}"
ProjectSection(SolutionItems) = preProject
Performance1.psess = Performance1.psess
Performance2.psess = Performance2.psess
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
Release2|Win32 = Release2|Win32
Release2|x64 = Release2|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{22A4991F-1B7C-463F-BB36-AA539CA28F4A}.Debug|Win32.ActiveCfg = Debug|Win32
{22A4991F-1B7C-463F-BB36-AA539CA28F4A}.Debug|Win32.Build.0 = Debug|Win32
{22A4991F-1B7C-463F-BB36-AA539CA28F4A}.Debug|x64.ActiveCfg = Debug|x64
{22A4991F-1B7C-463F-BB36-AA539CA28F4A}.Debug|x64.Build.0 = Debug|x64
{22A4991F-1B7C-463F-BB36-AA539CA28F4A}.Release|Win32.ActiveCfg = Release|Win32
{22A4991F-1B7C-463F-BB36-AA539CA28F4A}.Release|Win32.Build.0 = Release|Win32
{22A4991F-1B7C-463F-BB36-AA539CA28F4A}.Release|x64.ActiveCfg = Release|x64
{22A4991F-1B7C-463F-BB36-AA539CA28F4A}.Release|x64.Build.0 = Release|x64
{22A4991F-1B7C-463F-BB36-AA539CA28F4A}.Release2|Win32.ActiveCfg = Release2|Win32
{22A4991F-1B7C-463F-BB36-AA539CA28F4A}.Release2|Win32.Build.0 = Release2|Win32
{22A4991F-1B7C-463F-BB36-AA539CA28F4A}.Release2|x64.ActiveCfg = Release2|x64
{22A4991F-1B7C-463F-BB36-AA539CA28F4A}.Release2|x64.Build.0 = Release2|x64
{58AD3A6F-900A-46F6-947E-80D31DF1A60E}.Debug|Win32.ActiveCfg = Debug|Win32
{58AD3A6F-900A-46F6-947E-80D31DF1A60E}.Debug|Win32.Build.0 = Debug|Win32
{58AD3A6F-900A-46F6-947E-80D31DF1A60E}.Debug|x64.ActiveCfg = Debug|x64
{58AD3A6F-900A-46F6-947E-80D31DF1A60E}.Debug|x64.Build.0 = Debug|x64
{58AD3A6F-900A-46F6-947E-80D31DF1A60E}.Release|Win32.ActiveCfg = Release|Win32
{58AD3A6F-900A-46F6-947E-80D31DF1A60E}.Release|Win32.Build.0 = Release|Win32
{58AD3A6F-900A-46F6-947E-80D31DF1A60E}.Release|x64.ActiveCfg = Release|x64
{58AD3A6F-900A-46F6-947E-80D31DF1A60E}.Release|x64.Build.0 = Release|x64
{58AD3A6F-900A-46F6-947E-80D31DF1A60E}.Release2|Win32.ActiveCfg = Release2|Win32
{58AD3A6F-900A-46F6-947E-80D31DF1A60E}.Release2|Win32.Build.0 = Release2|Win32
{58AD3A6F-900A-46F6-947E-80D31DF1A60E}.Release2|x64.ActiveCfg = Release2|x64
{58AD3A6F-900A-46F6-947E-80D31DF1A60E}.Release2|x64.Build.0 = Release2|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

38
Research.v12.sln Normal file
View File

@@ -0,0 +1,38 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.31101.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Research", "Research\Research.v12.vcxproj", "{22A4991F-1B7C-463F-BB36-AA539CA28F4A}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OctreeBuilder.v12", "OctreeBuilder\OctreeBuilder.v12.vcxproj", "{58AD3A6F-900A-46F6-947E-80D31DF1A60E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug_v12|Win32 = Debug_v12|Win32
Debug_v12|x64 = Debug_v12|x64
Release_v12|Win32 = Release_v12|Win32
Release_v12|x64 = Release_v12|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{22A4991F-1B7C-463F-BB36-AA539CA28F4A}.Debug_v12|Win32.ActiveCfg = Debug|Win32
{22A4991F-1B7C-463F-BB36-AA539CA28F4A}.Debug_v12|Win32.Build.0 = Debug|Win32
{22A4991F-1B7C-463F-BB36-AA539CA28F4A}.Debug_v12|x64.ActiveCfg = Debug|x64
{22A4991F-1B7C-463F-BB36-AA539CA28F4A}.Debug_v12|x64.Build.0 = Debug|x64
{22A4991F-1B7C-463F-BB36-AA539CA28F4A}.Release_v12|Win32.ActiveCfg = Release|Win32
{22A4991F-1B7C-463F-BB36-AA539CA28F4A}.Release_v12|Win32.Build.0 = Release|Win32
{22A4991F-1B7C-463F-BB36-AA539CA28F4A}.Release_v12|x64.ActiveCfg = Release|x64
{22A4991F-1B7C-463F-BB36-AA539CA28F4A}.Release_v12|x64.Build.0 = Release|x64
{58AD3A6F-900A-46F6-947E-80D31DF1A60E}.Debug_v12|Win32.ActiveCfg = Debug|Win32
{58AD3A6F-900A-46F6-947E-80D31DF1A60E}.Debug_v12|Win32.Build.0 = Debug|Win32
{58AD3A6F-900A-46F6-947E-80D31DF1A60E}.Debug_v12|x64.ActiveCfg = Debug|x64
{58AD3A6F-900A-46F6-947E-80D31DF1A60E}.Debug_v12|x64.Build.0 = Debug|x64
{58AD3A6F-900A-46F6-947E-80D31DF1A60E}.Release_v12|Win32.ActiveCfg = Release|Win32
{58AD3A6F-900A-46F6-947E-80D31DF1A60E}.Release_v12|Win32.Build.0 = Release|Win32
{58AD3A6F-900A-46F6-947E-80D31DF1A60E}.Release_v12|x64.ActiveCfg = Release|x64
{58AD3A6F-900A-46F6-947E-80D31DF1A60E}.Release_v12|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

119
Research/PropertyLoader.cpp Normal file
View File

@@ -0,0 +1,119 @@
#include <fstream>
#include "PropertyLoader.h"
#include <algorithm>
#include <stdio.h>
#include <iterator>
#include <vector>
#include <string>
PropertyLoader* PropertyLoader::mInstance = NULL;
void PropertyLoader::Create() {
if (mInstance == NULL)
mInstance = new PropertyLoader();
}
void PropertyLoader::Destroy() {
if (mInstance != NULL)
delete mInstance;
mInstance = NULL;
}
PropertyLoader* PropertyLoader::Instance() {
return mInstance;
}
void PropertyLoader::Update() {
for (std::string propertyFile : mPropertyFiles)
LoadProperties(propertyFile.c_str());
}
void PropertyLoader::Clear()
{
mProperties.clear();
mPropertyFiles.clear();
}
void PropertyLoader::AddPropertyFile(std::string file)
{
mPropertyFiles.push_back(file);
Update();
}
//************************************
// Get property value based on its identifier
//************************************
std::string PropertyLoader::GetProperty(const std::string& id) {
auto res = mProperties.find(id);
if (res == mProperties.end()) return "";
return res->second;
}
unsigned PropertyLoader::GetIntProperty(const std::string& id)
{
return std::stoi(GetProperty(id));
}
float PropertyLoader::GetFloatProperty(const std::string& id)
{
return std::stof(GetProperty(id));
}
bool PropertyLoader::GetBoolProperty(const std::string& id)
{
std::string prop = GetProperty(id);
std::string upperProp;
std::transform(prop.begin(), prop.end(), std::back_inserter(upperProp), toupper);
return prop == "1" || upperProp == "TRUE";
}
std::vector<std::string> PropertyLoader::GetListProperty(const std::string &id)
{
bool found = true;
size_t index = 0;
std::vector<std::string> res = std::vector<std::string>();
while (found)
{
std::string toSearch = id + std::to_string(index);
std::string prop = GetProperty(toSearch);
found = prop != "";
if (found) res.push_back(prop);
index++;
}
return res;
}
PropertyLoader::PropertyLoader() {
LoadDefaults();
Update();
}
PropertyLoader::~PropertyLoader() {
mProperties.clear();
}
void PropertyLoader::LoadProperties(const char* fileName) {
std::ifstream properties(fileName);
std::string property;
while (getline(properties, property)) {
std::size_t pos = property.find(" ");
if (pos < property.npos) {
std::string left = property.substr(0, pos);
std::string right = property.substr(pos + 1);
// Remove newline characters
right.erase(std::remove(right.begin(), right.end(), '\r'), right.end());
right.erase(std::remove(right.begin(), right.end(), '\n'), right.end());
std::pair<std::map<std::string, std::string>::iterator, bool> loc = mProperties.insert(std::pair<std::string, std::string>(left, right));
if (!loc.second)
loc.first->second = right;
}
}
properties.close();
}
void PropertyLoader::LoadDefaults() {
mPropertyFiles.clear();
mPropertyFiles.push_back(std::string("shaders/shader_properties.txt"));
mPropertyFiles.push_back(std::string("properties.txt"));
}

35
Research/PropertyLoader.h Normal file
View File

@@ -0,0 +1,35 @@
#pragma once
#include <string>
#include <map>
#include <vector>
class PropertyLoader
{
public:
static void Create();
static void Destroy();
static PropertyLoader* Instance();
void Update();
void Clear();
void AddPropertyFile(std::string file);
std::string GetProperty(const std::string& id);
unsigned GetIntProperty(const std::string& id);
float GetFloatProperty(const std::string& id);
bool GetBoolProperty(const std::string& id);
std::vector<std::string> GetListProperty(const std::string& id);
std::map<std::string, std::string> mProperties;
protected:
private:
PropertyLoader();
~PropertyLoader();
void LoadProperties(const char* fileName);
void LoadDefaults();
static PropertyLoader* mInstance;
std::vector<std::string> mPropertyFiles;
};

135
Research/Readme.txt Normal file
View File

@@ -0,0 +1,135 @@
Settings for the research project can be found in:
properties.txt
shaders/shader_properties.txt
Settings are ordered as the settings name (cannot contain spaces!), followed by it's value.
Main settings:
anti_aliasing:
Number of samples used for anti-aliasing. Should be a power of two.
opengl_version_major:
OpenGL version used (e.g. 4.x)
opengl_version_minor:
Minor OpenGL version used. This is the number behind the dot in the openGL version number.
OctreeBuilder settings:
octreebuilder_debug_width:
The width of the debug window the octree builder renders in (in pixels)
octreebuilder_debug_height:
The height of the debug window the octree builder renders in (in pixels)
octreebuilder_manual:
In manual mode, the user should press space to go to the next layer of the depth peeling. (1 for on, 0 for off)
octreebuilder_renderscene:
Boolean indicating if the scene should be rendered directly, or if the buffer read using depth peeling should be rendered to a fullscereen quad (1 for scene rendering, 0 for buffer rendering)
octreebuilder_verbose:
Boolean indicating if the octreebuilder should output progress information
octreebuilder_interpolate_colors:
If 1, mipmaps and linear interpolation will be used, if 0, nearest neighbor will be used.
octreebuilder_usecache:
If 1, the octreebuilder will check if a tree exists before building it.
octreebuilder_max_single_pass_layers:
The maximum number of layers that can be constructed at once. If the required depth is higher than this number, the scene will be split up in required cells, which will then be converted into octrees.
octreebuilder_poolsize
The maximum size that the ObjectPool used for Nodes can be (in number of nodes)
Renderer settings:
vertex_shader:
Filename (relative to "<<Current Folder>>/shaders/") of the vertex shader to be used.
fragment_shader:
Filename (relative to "<<Current Folder>>/shaders/") of the fragment shader to be used for default (colored or uncolored) octrees
fragment_shader_multiroot:
Filename (relative to "<<Current Folder>>/shaders/") of the fragment shader to be used for mutliroot trees that contain a certain number of bits per tree
renderer_usecache:
Boolean indicating if the pool texture should be loaded from disk (if it exists) or generated directly.
renderer_showLeafCount:
Boolean indicating if the total number of leaf voxels should be calculated and printed.
verbose:
Boolean indicating if the renderer should output progress information
width:
The width of the renderer window
height:
The height of the renderer window
window_name:
The title of the window (as shown by windows)
octree_type:
The type of octree to be used. Currently supported are:
s
Standard binary octree/DAG as described by Kämpe and Assarsson in High Resolution Sparse Voxel DAGs
hc<<compression>
Hierarchical Colored Octree/DAG: Colored tree in which all nodes in the tree can contain colors (not just the leafs). The actual colors are stored in a seperate texture. Each node in the tree contains a pointer to this texture. The average color of the child nodes is used as the color of a node.
hsc<<compression>
Hierarchical Shift Colored Octree: stores in each node the difference with it's parent node. Note that for this to work, the shader needs to be changed manually to a shader that supports these kinds of trees.
oc<<compression>
Only-Colors Colored Octree/DAG: Hierarchical Octree type that uses two trees. The first tree contains the correct colors in the position where there is geometry, but the rest of the tree can be filled up to increase the number of identical nodes for DAG merging. A second octree is used for geometry. This is an "s" tree.
u([0-9]+lod)?([0-9]+|t|p|b)c<<compression>>
Unique-Index Colored Octree/DAG: The geometry is stored in a DAG (similar to "s"), and on each edge in index shift is stored. This index shift makes sure that each node in the original octree gets a unique index. These indexes are then used to find the material in a second data structure.
The keyword "[0-9]+lod" is optional, and can be used to define the number of levels on which no material information should be stored (e.g. don't give a unique index to the last x layers in the tree, but make their indices equal to that of the parents, reducing the size of the material texture).
The number behind the "u" indicates the block sized to be used for block compression: The material pointer texture is compressed by splitting it up into blocks of equal size, removing duplicate blocks, and storing pointers to blocks of the same size. If the block size is very big, compression will not work well since no identical blocks will be found. If the block size is too small however, the compression will also fail as the amount of block pointers will become similar to the number of blocks.
mcc:
MultiRoot with one color channel per tree.
m[1-8]*
Multiroot DAG: in this DAG multiple octrees will be compressed into one DAG with several roots. The number behind the "m" indicates the number of bits per color channel. Each tree describes one bit of the color for every voxel in the scene. If no number is given, all 8 bits will be used per color channel. A lower number can be used leading to lossy compression.
m[1-8]b[1-8]:
MultiRoot octree in which more than one bit of information can be stored per tree. The number behind the m indicates the precision per color channel (in bits). The number behind the b indicates how many bits can be stored in one tree. "b1" is thus equal to "m[1-8]" trees.
The compression specifiers available are:
[0-9]+
Compression algorithm based on the paper "Color Image Quantization by Minimizing the Maximum Intercluster Distance" by Zhigang Xiang. It merges colors together until the desired amount of colors is left. Merging is done based on the distance in RGB space, with some mulitpliers to make it more visually uniform
lab[0-9]+
Same clustering algorithm, as [0-9]+, but the colors are converted to the CIELAB color space before being compressed
de[0-9]+.[0-9]+
Delta-E compression: greedy algorithm in which colors are merged to clusters such that the maximum delta-E within a cluster is given by the value passed. E.g. de2.7 leads to clusters within which the maximum delta-e from the cluster center is 2.7.
b[0-8]:
Cuts the colors so that they contain only the given number of bits
pool_type:
The way the tree should be stored in the GPU. Options are:
s
Standard way. Pointers have a fixed size per level, and are relative to the start of the level, saving some space as most levels can use pointers of less than 4 bytes.
o
Original method proposed in Kämpe et al's DAGs paper.
ad<<maskSize>><<maskByteSizes>>
Adaptive pointer sizes. First two bits of each pointer describe the size of the pointer. Nodes are ordered such that the most used nodes have the smallest pointers.
MaskSize indicates the size of the mask to be used (1 or 2 bits)
maskByteSizes: array of 3 numbers indicating the size of each pointer in the consecutive mask options.
al<<maskSize>><<maskByteSizes>>
Adaptive pointer sizes with lookup table. Pointers that are shortened point to an index in a lookup table. This means that all nodes have consecutive indices in this lookup table.
MaskSize indicates the size of the mask to be used (1 or 2 bits).
maskByteSizes: array of 3 numbers indicating the size of each pointer in the consecutive mask options.
v
Virtual nodes: Only one pointer is stored per node: one to the first child of that node. If nodes are not merged, this works perfectly. For nodes that are merged, "virtual nodes" are used. These nodes are just pointers to the actual node in memory.
obj_to_dag:
Filename of the OBJ file to be converted to a DAG and rendered (relative to the current working directory)
dag_file:
Filename of the tree and pool to be generated (relative to the current working directory
Renderer controls:
Movement WASD || Arrow keys
Strafing Q and E
Rotation Mouse
Zoom Scrollwheel
Triple movement speed/Running Shift
Slow movement speed/Crawling Left Ctrl
Increase/Decrease movement speed =/-
Toggle fullscreen F
Reset camera X
Change camera mode C
Change Octree render depth [ and ]
Update light direction L
Toggle Light K
Toggle AO/GI method J
Reload shaders R
Recording controls:
Take screenshot P
Goto preset location (from settings) Number keys (0-9)
Store current viewpoint N
Goto last stored viewpoint M
Start/Stop camerapath recording V
Store screenshots along camerapath B
Start/Stop a benchmark/flythrough G
Clear the camera path recording T
Add a node to the camerapath Y
Pop the last node from the camerapath Ctrl + Y
Clear the light path recording I
Add a node to the light path O

1455
Research/Renderer.cpp Normal file

File diff suppressed because it is too large Load Diff

186
Research/Renderer.h Normal file
View File

@@ -0,0 +1,186 @@
#pragma once
#include <vector>
#include <map>
#include "scene/Scene.h"
#include "core/CameraPath.h"
#include "core/LightPath.h"
#include "core/Defines.h"
#include "core/Util/Stopwatch.h"
class Camera;
class Controls;
class ObjLoader;
class ShaderLoader;
class PropertyLoader;
struct GLFWwindow;
class Renderer {
private:
// X and Y size of textures
const static unsigned TEXTURE_SIZE = 1024;
// The size (in the Z direction) of a single texture block
const static unsigned TEXTURE_BLOCK_SIZE = 1024;
public:
static void Create();
static void Destroy();
static Renderer* Instance();
void Render();
bool Initialize(bool fullscreen = false);
static size_t Load2DTexture(std::string filename);
void ToggleFullscreen(bool fullscreen);
void ReloadShaders();
void UpdateLightDirection();
void ToggleLight();
void ToggleAOMode();
void ToggleReflections();
void TakeScreenshot();
void SetPresetLocation(unsigned8 presetID);
// Starts and stops recording a camera path. Use StoreRecording() after calling this method to store screenshots along the path
void ToggleRecording();
void ClearLightPath();
void AddLightPathNode();
void ClearCameraPath();
void AddCameraPathNode();
void RemoveCameraPathNode();
/// Clears the camera path and replaces it with a rotation.
void SetRotationRecording();
// Stores screenshot along every path position of the last recording
void StoreRecording();
// Goes through the current camera path and stores the frame time for each frame.
void RunBenchmark();
void SaveLastViewpoint();
void LoadLastViewpoint();
void Resize(int width, int height);
void IncreaseOctreeRenderLevel();
void DecreaseOctreeRenderLevel();
private:
Renderer();
~Renderer();
bool Reinitialize(bool fullscreen);
bool InitializeGLFW(bool fullscreen);
void Transform();
void SetCameraState(CameraState state);
void InitFramebuffer();
void DeleteFramebuffer();
void SetStaticUniforms(unsigned program);
void SetDynamicUniforms(unsigned program);
void LoadOctree();
void GenerateRandomTexture();
void LoadFragmentShaderUniforms();
void LoadShaders();
void SaveViewpoint(std::string filename);
void LoadViewpoint(std::string filename);
void SaveRecording(std::string filename);
void LoadRecording(std::string filename);
void SaveLightPathRecording(std::string filename);
void LoadLightPathRecording(std::string filename);
void StartFlythrough();
void StopFlythrough();
void StartStoringRecording();
void StopStoringRecording();
void StartBenchmark();
void StopBenchmark();
void InitRecordingDirectory();
static void Resize(GLFWwindow* window, int width, int height);
bool textureLoaded(std::string filename);
void TakeScreenshot(std::string filename);
static Renderer* mInstance;
int mWidth;
int mHeight;
int mWidthOld;
int mHeightOld;
bool mUseCache;
unsigned8 mMaxLevel;
unsigned8 mRenderDepth;
std::string mTreeType;
GLFWwindow* mWindow;
Camera* mCamera;
Controls* mController;
ObjLoader* mObjLoader;
ShaderLoader* mShaderLoader;
PropertyLoader* mPropertyLoader;
enum AOMode{ NONE, REAL, SSAO, NUM_VALUES };
AOMode mAOMode;
bool mReflections;
unsigned mVertexArrayID, mVertexBuffer, mTextureBuffer, mNormalBuffer, mElementBuffer, mDefaultProgramID, mPostProcessProgramID, mGiPostProcessProgramID, mRenderDepthUniform;
unsigned mFramebuffer, mFramebufferTexture, mDirectLightTexture, mIndirectLightTexture, mVoxelPositionsTexture, mDepthTexture, mQuadVertexBuffer, mPostprocessRenderTextureUniform, mPostprocessVoxelPositionsTextureUniform, mPostprocessDepthTextureUniform, mGiPostProcessRenderTextureUniform, mGiPostProcessDirectLightTextureUniform, mGiPostProcessIndirectLightTextureUniform;
CameraState mCurrentCameraState;
LightState mLightState;
DirectionalLight mDirectionalLight;
PointLight mPointLight;
glm::mat4 mModelMatrix;
glm::mat4 mViewMatrix;
glm::mat4 mProjectionMatrix;
glm::mat4 mMVP;
glm::mat4 mInvMVP;
Scene* mScene;
std::map<std::string, unsigned> mTextures; // list of all textures
std::vector<unsigned32> mOctreeTextures;
std::vector<unsigned32> mBlockTextures;
// for binding the texture sampler
unsigned mTextureSampler, mMaterialOctreeSampler, mOctreeSamplers, mMaterialTextureSampler, mBlockPointerSampler, mBlockSamplers, mRandomTextureSampler;
unsigned mMaterialTexture, mMaterialOctreeTexture, mBlockPointerTexture, mRandomTexture;
std::map<std::string, std::string> mAdditionalProperties;
std::map<unsigned, bool> mStaticUniformsSet; // flag that static uniforms have been set
double mLastTime;
double mCurrentTime;
unsigned mFrames;
char mText[100];
std::string mDagFilename;
std::string mScreenshotDirectory;
// The actual recording (camera states and times)
CameraPath mCameraPath;
LightPath mLightPath;
// Properties used for camera path recording
Stopwatch mRecordingTimer;
bool mIsRecording;
// Properties used for video storing
bool mIsStoringRecording;
bool mIsTrackballReconding;
bool mIsPlayingFlythrough;
// Index of the current frame
unsigned mCameraPathFrame;
// Time per frame (1.0 / FPS)
float mRecordingFPS;
float mCameraPathFrameTime;
float mCameraPathNodeTime;
float mLightPathNodeTime;
// Stats for benchmarking:
std::vector<double> mFrameTimes;
// Directory of the images for the current recording
std::string mRecordingDirectory;
static const float QUAD_VERTEX_BUFFER_DATA[];
};

View File

@@ -0,0 +1,414 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.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="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release2|Win32">
<Configuration>Release2</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release2|x64">
<Configuration>Release2</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{22A4991F-1B7C-463F-BB36-AA539CA28F4A}</ProjectGuid>
<RootNamespace>Research</RootNamespace>
<ProjectName>Research</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release2|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release2|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</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 Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<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>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release2|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release2|x64'" Label="PropertySheets">
<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'">
<LibraryPath>$(ProjectDir)\lib32;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LibraryPath>$(ProjectDir)\lib64;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LibraryPath>$(ProjectDir)\lib32;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release2|Win32'">
<LibraryPath>$(ProjectDir)\lib32;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LibraryPath>$(ProjectDir)\lib64;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release2|x64'">
<LibraryPath>$(ProjectDir)\lib64;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>glfw3.lib;opengl32.lib;glew32.lib;assimp.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalOptions>/VERBOSE:LIB %(AdditionalOptions)</AdditionalOptions>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>glfw3.lib;opengl32.lib;glew32.lib;assimp.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalOptions>/VERBOSE:LIB %(AdditionalOptions)</AdditionalOptions>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Full</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<AdditionalDependencies>glfw3.lib;opengl32.lib;glew32.lib;assimp.lib;%(AdditionalDependencies)</AdditionalDependencies>
<Profile>true</Profile>
<AdditionalOptions>/VERBOSE:LIB %(AdditionalOptions)</AdditionalOptions>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release2|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Full</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<FavorSizeOrSpeed>Neither</FavorSizeOrSpeed>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>glfw3.lib;opengl32.lib;glew32.lib;assimp.lib;%(AdditionalDependencies)</AdditionalDependencies>
<Profile>true</Profile>
<AdditionalOptions>/VERBOSE:LIB %(AdditionalOptions)</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Full</Optimization>
<SDLCheck>true</SDLCheck>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<AdditionalDependencies>glfw3.lib;opengl32.lib;glew32.lib;assimp.lib;%(AdditionalDependencies)</AdditionalDependencies>
<Profile>true</Profile>
<AdditionalOptions>/VERBOSE:LIB %(AdditionalOptions)</AdditionalOptions>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release2|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Full</Optimization>
<SDLCheck>true</SDLCheck>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>glfw3.lib;opengl32.lib;glew32.lib;assimp.lib;%(AdditionalDependencies)</AdditionalDependencies>
<Profile>true</Profile>
<AdditionalOptions>/VERBOSE:LIB %(AdditionalOptions)</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="core\BitHelper.h" />
<ClInclude Include="core\Camera.h" />
<ClInclude Include="core\CameraPath.h" />
<ClInclude Include="core\CollectionHelper.h" />
<ClInclude Include="core\ColorHelper.h" />
<ClInclude Include="core\Comparers.h" />
<ClInclude Include="core\CompileTimeArray.h" />
<ClInclude Include="core\Controls.h" />
<ClInclude Include="core\Defines.h" />
<ClInclude Include="core\Hashers.h" />
<ClInclude Include="core\IntersectTests.h" />
<ClInclude Include="core\LightPath.h" />
<ClInclude Include="core\MathHelper.h" />
<ClInclude Include="core\OctreeBuilder\BaseMaterialOctreeBuilder.h" />
<ClInclude Include="core\OctreeBuilder\BaseOctreeBuilder.h" />
<ClInclude Include="core\OctreeBuilder\ColorAndValueQuantizerFactory.h" />
<ClInclude Include="core\OctreeBuilder\ColorChannelMultiRootOctreeBuilder.h" />
<ClInclude Include="core\OctreeBuilder\ColorQuantizerFactory.h" />
<ClInclude Include="core\OctreeBuilder\CompressedTextureFactory.h" />
<ClInclude Include="core\OctreeBuilder\HierarchicalMaterialOctreeBuilder.h" />
<ClInclude Include="core\OctreeBuilder\MaterialLibraryMultiRootOctreeBuilder.h" />
<ClInclude Include="core\OctreeBuilder\MaterialMultiRootOctreeBuilder.h" />
<ClInclude Include="core\OctreeBuilder\MultiBitsMultiRootOctreeBuilder.h" />
<ClInclude Include="core\OctreeBuilder\MultiRootOctreeBuilder.h" />
<ClInclude Include="core\OctreeBuilder\OctreeBuilder.h" />
<ClInclude Include="core\OctreeBuilder\OctreeBuilderStatistics.h" />
<ClInclude Include="core\OctreeBuilder\OctreeConverter.h" />
<ClInclude Include="core\OctreeBuilder\OctreeLoader.h" />
<ClInclude Include="core\OctreeBuilder\PoolBuilderFactory.h" />
<ClInclude Include="core\OctreeBuilder\RandomOctreeBuilder.h" />
<ClInclude Include="core\OctreeBuilder\SettingsParser.h" />
<ClInclude Include="core\OctreeBuilder\StandardOctreeBuilder.h" />
<ClInclude Include="core\OctreeBuilder\TreeTypeParser.h" />
<ClInclude Include="core\OctreeBuilder\UniqueIndexMaterialOctreeBuilder.h" />
<ClInclude Include="core\OctreeBuilder\UniqueIndexShiftColoredOctreeBuilder.h" />
<ClInclude Include="core\PathHelper.h" />
<ClInclude Include="core\Serializer.h" />
<ClInclude Include="core\StringHelper.h" />
<ClInclude Include="core\Util\BinaryTree.h" />
<ClInclude Include="core\Util\BlockVector.h" />
<ClInclude Include="core\Util\BoolArray.h" />
<ClInclude Include="core\Util\IndexIterator.h" />
<ClInclude Include="core\Util\ObjectPool.h" />
<ClInclude Include="core\Util\Path.h" />
<ClInclude Include="core\Util\SmallDynamicArray.h" />
<ClInclude Include="core\Util\Stopwatch.h" />
<ClInclude Include="core\Util\TransferFunction.h" />
<ClInclude Include="core\Voxelizer\BaseVoxelizer.h" />
<ClInclude Include="core\Voxelizer\PVMVoxelizer.h" />
<ClInclude Include="core\Voxelizer\TriangleMeshVoxelizer.h" />
<ClInclude Include="core\Voxelizer\VoxelInfo.h" />
<ClInclude Include="inc\lodepng\lodepng.h" />
<ClInclude Include="inc\pvm\codebase.h" />
<ClInclude Include="inc\pvm\ddsbase.h" />
<ClInclude Include="PropertyLoader.h" />
<ClInclude Include="Renderer.h" />
<ClInclude Include="scene\DirectionalLight.h" />
<ClInclude Include="scene\Material\BaseMaterial.h" />
<ClInclude Include="scene\Material\BitsMaterial.h" />
<ClInclude Include="scene\Material\Block.h" />
<ClInclude Include="scene\Material\BlockBasedMaterialLibrary.h" />
<ClInclude Include="scene\Material\Color.h" />
<ClInclude Include="scene\Material\ColorAndNormal.h" />
<ClInclude Include="scene\Material\ColorAndNormalAndValue.h" />
<ClInclude Include="scene\Material\ColorAndOpacity.h" />
<ClInclude Include="scene\Material\ColorAndValue.h" />
<ClInclude Include="scene\Material\ColorChannel.h" />
<ClInclude Include="scene\Material\MaterialLibrary.h" />
<ClInclude Include="scene\Material\MaterialLibraryPointer.h" />
<ClInclude Include="scene\Material\MaterialPair.h" />
<ClInclude Include="scene\Material\MaterialQuantizer\BaseQuantizer.h" />
<ClInclude Include="scene\Material\MaterialQuantizer\ColorAndValueQuantizer.h" />
<ClInclude Include="scene\Material\MaterialQuantizer\ColorQuantizer\BaseColorQuantizer.h" />
<ClInclude Include="scene\Material\MaterialQuantizer\ColorQuantizer\ColorBitCutter.h" />
<ClInclude Include="scene\Material\MaterialQuantizer\ColorQuantizer\MaxErrorClusterer.h" />
<ClInclude Include="scene\Material\MaterialQuantizer\ColorQuantizer\XiangCIELABClusterer.h" />
<ClInclude Include="scene\Material\MaterialQuantizer\ColorQuantizer\XiangClusterer.h" />
<ClInclude Include="scene\Material\NearestFinder.h" />
<ClInclude Include="scene\Material\SignedIntMaterial.h" />
<ClInclude Include="scene\Material\SmallNormal.h" />
<ClInclude Include="scene\ObjLoader.h" />
<ClInclude Include="scene\Octree\BaseTree.h" />
<ClInclude Include="scene\Octree\ChildMask.h" />
<ClInclude Include="scene\Octree\ColorChannelMultiRootTree.h" />
<ClInclude Include="scene\Octree\EdgeMaterialNode.h" />
<ClInclude Include="scene\Octree\HierarchicalColorsOnlyTree.h" />
<ClInclude Include="scene\Octree\HierarchicalMaterialMultiRoot.h" />
<ClInclude Include="scene\Octree\HierarchicalShiftingColoredTree.h" />
<ClInclude Include="scene\Octree\IAdditionalProperties.h" />
<ClInclude Include="scene\Octree\IBlockTexture.h" />
<ClInclude Include="scene\Octree\IMaterialTexture.h" />
<ClInclude Include="scene\Octree\LeafMaterialMultiRootTree.h" />
<ClInclude Include="scene\Octree\MaterialLibraryMultiRootTree.h" />
<ClInclude Include="scene\Octree\MaterialLibraryTree.h" />
<ClInclude Include="scene\Octree\MaterialLibraryUniqueIndexTree.h" />
<ClInclude Include="scene\Octree\MaterialNode.h" />
<ClInclude Include="scene\Octree\MaterialTree.h" />
<ClInclude Include="scene\Octree\MultiRootBitsTree.h" />
<ClInclude Include="scene\Octree\MultiRootTree.h" />
<ClInclude Include="scene\Octree\Node.h" />
<ClInclude Include="scene\Octree\NodeReplacementFinder.h" />
<ClInclude Include="scene\Octree\NodeSmall.h" />
<ClInclude Include="scene\Octree\Tree.h" />
<ClInclude Include="scene\Octree\UniqueIndexShiftTree.h" />
<ClInclude Include="scene\Octree\UniqueIndexTree.h" />
<ClInclude Include="scene\PNG.h" />
<ClInclude Include="scene\PointLight.h" />
<ClInclude Include="scene\PoolBuilder\AdaptivePointerPoolBuilder.h" />
<ClInclude Include="scene\PoolBuilder\BasePoolBuilder.h" />
<ClInclude Include="scene\PoolBuilder\BaseTreePoolBuilder.h" />
<ClInclude Include="scene\PoolBuilder\OriginalPoolBuilder.h" />
<ClInclude Include="scene\PoolBuilder\StandardPoolBuilder.h" />
<ClInclude Include="scene\PoolBuilder\VirtualNodePoolBuilder.h" />
<ClInclude Include="scene\Scene.h" />
<ClInclude Include="scene\TextureCompressor\BasicTexture.h" />
<ClInclude Include="scene\TextureCompressor\BlockCompressedTexture.h" />
<ClInclude Include="scene\TextureCompressor\BlockHashers.h" />
<ClInclude Include="scene\TextureCompressor\CompressedTexture.h" />
<ClInclude Include="scene\TextureCompressor\DagBasedTexture.h" />
<ClInclude Include="scene\TextureCompressor\MultiRootBasedTexture.h" />
<ClInclude Include="scene\TextureCompressor\PaletteBlockTexture.h" />
<ClInclude Include="scene\TextureCompressor\TightlyPackedTexture.h" />
<ClInclude Include="shaders\ShaderLoader.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="core\Camera.cpp" />
<ClCompile Include="core\CameraPath.cpp" />
<ClCompile Include="core\ColorHelper.cpp" />
<ClCompile Include="core\Controls.cpp" />
<ClCompile Include="core\IntersectTests.cpp" />
<ClCompile Include="core\LightPath.cpp" />
<ClCompile Include="core\OctreeBuilder\BaseOctreeBuilder.cpp" />
<ClCompile Include="core\OctreeBuilder\ColorQuantizerFactory.cpp" />
<ClCompile Include="core\OctreeBuilder\MaterialLibraryMultiRootOctreeBuilder.cpp" />
<ClCompile Include="core\OctreeBuilder\MultiRootOctreeBuilder.cpp" />
<ClCompile Include="core\OctreeBuilder\OctreeBuilder.cpp" />
<ClCompile Include="core\OctreeBuilder\OctreeConverter.cpp" />
<ClCompile Include="core\OctreeBuilder\OctreeLoader.cpp" />
<ClCompile Include="core\OctreeBuilder\RandomOctreeBuilder.cpp" />
<ClCompile Include="core\OctreeBuilder\SettingsParser.cpp" />
<ClCompile Include="core\OctreeBuilder\StandardOctreeBuilder.cpp" />
<ClCompile Include="core\OctreeBuilder\TreeTypeParser.cpp" />
<ClCompile Include="core\OctreeBuilder\UniqueIndexShiftColoredOctreeBuilder.cpp" />
<ClCompile Include="core\PathHelper.cpp" />
<ClCompile Include="core\StringHelper.cpp" />
<ClCompile Include="core\Util\BoolArray.cpp" />
<ClCompile Include="core\Util\Stopwatch.cpp" />
<ClCompile Include="core\Voxelizer\PVMVoxelizer.cpp" />
<ClCompile Include="core\Voxelizer\TriangleMeshVoxelizer.cpp" />
<ClCompile Include="inc\lodepng\lodepng.cpp" />
<ClCompile Include="inc\pvm\ddsbase.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="PropertyLoader.cpp" />
<ClCompile Include="Renderer.cpp" />
<ClCompile Include="scene\DirectionalLight.cpp" />
<ClCompile Include="scene\Material\Color.cpp" />
<ClCompile Include="scene\Material\ColorChannel.cpp" />
<ClCompile Include="scene\Material\MaterialQuantizer\ColorQuantizer\ColorBitCutter.cpp" />
<ClCompile Include="scene\Material\MaterialQuantizer\ColorQuantizer\MaxErrorClusterer.cpp" />
<ClCompile Include="scene\Material\MaterialQuantizer\ColorQuantizer\XiangCIELABClusterer.cpp" />
<ClCompile Include="scene\Material\MaterialQuantizer\ColorQuantizer\XiangClusterer.cpp" />
<ClCompile Include="scene\ObjLoader.cpp" />
<ClCompile Include="scene\Octree\BaseTree.cpp" />
<ClCompile Include="scene\Octree\HierarchicalColorsOnlyTree.cpp" />
<ClCompile Include="scene\Octree\HierarchicalShiftingColoredTree.cpp" />
<ClCompile Include="scene\Octree\Node.cpp" />
<ClCompile Include="scene\PNG.cpp" />
<ClCompile Include="scene\PointLight.cpp" />
<ClCompile Include="scene\PoolBuilder\AdaptivePointerPoolBuilder.cpp" />
<ClCompile Include="scene\PoolBuilder\BaseTreePoolBuilder.cpp" />
<ClCompile Include="scene\PoolBuilder\StandardPoolBuilder.cpp" />
<ClCompile Include="scene\PoolBuilder\VirtualNodePoolBuilder.cpp" />
<ClCompile Include="shaders\ShaderLoader.cpp" />
</ItemGroup>
<ItemGroup>
<None Include="shaders\CombinedStackRaytrace.frag" />
<None Include="shaders\DepthPeel.frag" />
<None Include="shaders\DepthPeel.vert" />
<None Include="shaders\Raytrace1.frag" />
<None Include="shaders\RenderTexture.vert" />
<None Include="shaders\RenderTexture.frag" />
<None Include="shaders\Shader.frag" />
<None Include="shaders\Shader.vert" />
<None Include="shaders\SSAO.frag" />
<None Include="shaders\SSAO2.frag" />
<None Include="shaders\StackRaytrace.frag" />
</ItemGroup>
<ItemGroup>
<Text Include="properties.txt" />
<Text Include="shaders\shader_properties.txt" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,596 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Core">
<UniqueIdentifier>{633bca08-629d-415e-9025-d35a00ed864e}</UniqueIdentifier>
</Filter>
<Filter Include="Scene">
<UniqueIdentifier>{abb43287-8c7b-4c8b-a210-7efeab2d8679}</UniqueIdentifier>
</Filter>
<Filter Include="Shaders">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="Core\OctreeBuilder">
<UniqueIdentifier>{a65dfa3d-c828-4996-aa18-119e8a46e50f}</UniqueIdentifier>
</Filter>
<Filter Include="Scene\Octree">
<UniqueIdentifier>{971f6a5b-d390-4b1f-ade3-9e66b60e384b}</UniqueIdentifier>
</Filter>
<Filter Include="Scene\Material">
<UniqueIdentifier>{e89d5220-655b-4777-8d9f-eadfd219b6a4}</UniqueIdentifier>
</Filter>
<Filter Include="Scene\Material\MaterialQuantizer">
<UniqueIdentifier>{e1796e23-6f5f-4851-b9a8-c38bbd2c6d2f}</UniqueIdentifier>
</Filter>
<Filter Include="Scene\Material\MaterialQuantizer\ColorQuantizer">
<UniqueIdentifier>{11b192c3-922f-4949-a591-e5790c04cdfa}</UniqueIdentifier>
</Filter>
<Filter Include="Scene\TextureCompressor">
<UniqueIdentifier>{a62fdf46-78ed-475b-88d0-a2bab6ed5ce6}</UniqueIdentifier>
</Filter>
<Filter Include="Core\Helpers">
<UniqueIdentifier>{dbe53c3a-dd4d-4f30-9c91-4d0611be2800}</UniqueIdentifier>
</Filter>
<Filter Include="Core\Util">
<UniqueIdentifier>{4339393f-4085-4c33-8666-bcca22eb2796}</UniqueIdentifier>
</Filter>
<Filter Include="Scene\PoolBuilder">
<UniqueIdentifier>{ef901ea6-d046-4226-aba0-1bf6cd6042a8}</UniqueIdentifier>
</Filter>
<Filter Include="Scene\PVM">
<UniqueIdentifier>{43a609b0-7d29-4c83-bb30-bdf483b21a43}</UniqueIdentifier>
</Filter>
<Filter Include="Core\Voxelizer">
<UniqueIdentifier>{dc495dc0-adec-4578-a785-444a19ed84e8}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Renderer.h" />
<ClInclude Include="core\Controls.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="core\Defines.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="scene\ObjLoader.h">
<Filter>Scene</Filter>
</ClInclude>
<ClInclude Include="scene\PNG.h">
<Filter>Scene</Filter>
</ClInclude>
<ClInclude Include="inc\lodepng\lodepng.h">
<Filter>Scene</Filter>
</ClInclude>
<ClInclude Include="shaders\ShaderLoader.h">
<Filter>Shaders</Filter>
</ClInclude>
<ClInclude Include="scene\Scene.h">
<Filter>Scene</Filter>
</ClInclude>
<ClInclude Include="PropertyLoader.h" />
<ClInclude Include="core\Camera.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="core\IntersectTests.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\BaseOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\MultiRootOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\OctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\OctreeBuilderStatistics.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\StandardOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="scene\DirectionalLight.h">
<Filter>Scene</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\ColorChannelMultiRootOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\MaterialMultiRootOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\MultiBitsMultiRootOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="core\Hashers.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="core\Comparers.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\OctreeConverter.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\OctreeLoader.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\CompressedTextureFactory.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="scene\Material\MaterialQuantizer\ColorQuantizer\BaseColorQuantizer.h">
<Filter>Scene\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClInclude>
<ClInclude Include="scene\Material\MaterialQuantizer\ColorQuantizer\MaxErrorClusterer.h">
<Filter>Scene\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClInclude>
<ClInclude Include="scene\Material\MaterialQuantizer\ColorQuantizer\XiangCIELABClusterer.h">
<Filter>Scene\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClInclude>
<ClInclude Include="scene\Material\MaterialQuantizer\ColorQuantizer\XiangClusterer.h">
<Filter>Scene\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClInclude>
<ClInclude Include="scene\Material\MaterialQuantizer\ColorQuantizer\ColorBitCutter.h">
<Filter>Scene\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClInclude>
<ClInclude Include="core\BitHelper.h">
<Filter>Core\Helpers</Filter>
</ClInclude>
<ClInclude Include="core\ColorHelper.h">
<Filter>Core\Helpers</Filter>
</ClInclude>
<ClInclude Include="core\StringHelper.h">
<Filter>Core\Helpers</Filter>
</ClInclude>
<ClInclude Include="core\CameraPath.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="core\CollectionHelper.h">
<Filter>Core\Helpers</Filter>
</ClInclude>
<ClInclude Include="core\MathHelper.h">
<Filter>Core\Helpers</Filter>
</ClInclude>
<ClInclude Include="core\CompileTimeArray.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="scene\TextureCompressor\BasicTexture.h">
<Filter>Scene\TextureCompressor</Filter>
</ClInclude>
<ClInclude Include="scene\TextureCompressor\BlockCompressedTexture.h">
<Filter>Scene\TextureCompressor</Filter>
</ClInclude>
<ClInclude Include="scene\TextureCompressor\BlockHashers.h">
<Filter>Scene\TextureCompressor</Filter>
</ClInclude>
<ClInclude Include="scene\TextureCompressor\CompressedTexture.h">
<Filter>Scene\TextureCompressor</Filter>
</ClInclude>
<ClInclude Include="scene\TextureCompressor\TightlyPackedTexture.h">
<Filter>Scene\TextureCompressor</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\RandomOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\MaterialLibraryMultiRootOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="core\Serializer.h">
<Filter>Core\Helpers</Filter>
</ClInclude>
<ClInclude Include="scene\TextureCompressor\DagBasedTexture.h">
<Filter>Scene\TextureCompressor</Filter>
</ClInclude>
<ClInclude Include="scene\TextureCompressor\MultiRootBasedTexture.h">
<Filter>Scene\TextureCompressor</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\TreeTypeParser.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\SettingsParser.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="scene\PoolBuilder\BasePoolBuilder.h">
<Filter>Scene\PoolBuilder</Filter>
</ClInclude>
<ClInclude Include="scene\PoolBuilder\StandardPoolBuilder.h">
<Filter>Scene\PoolBuilder</Filter>
</ClInclude>
<ClInclude Include="scene\PoolBuilder\BaseTreePoolBuilder.h">
<Filter>Scene\PoolBuilder</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\PoolBuilderFactory.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="scene\PoolBuilder\OriginalPoolBuilder.h">
<Filter>Scene\PoolBuilder</Filter>
</ClInclude>
<ClInclude Include="scene\PoolBuilder\AdaptivePointerPoolBuilder.h">
<Filter>Scene\PoolBuilder</Filter>
</ClInclude>
<ClInclude Include="scene\PoolBuilder\VirtualNodePoolBuilder.h">
<Filter>Scene\PoolBuilder</Filter>
</ClInclude>
<ClInclude Include="scene\TextureCompressor\PaletteBlockTexture.h">
<Filter>Scene\TextureCompressor</Filter>
</ClInclude>
<ClInclude Include="scene\Material\MaterialQuantizer\BaseQuantizer.h">
<Filter>Scene\Material\MaterialQuantizer</Filter>
</ClInclude>
<ClInclude Include="core\PathHelper.h">
<Filter>Core\Helpers</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\BaseMaterialOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\ColorAndValueQuantizerFactory.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\ColorQuantizerFactory.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\HierarchicalMaterialOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\UniqueIndexShiftColoredOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\UniqueIndexMaterialOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="core\Util\Stopwatch.h">
<Filter>Core\Util</Filter>
</ClInclude>
<ClInclude Include="core\Util\TransferFunction.h">
<Filter>Core\Util</Filter>
</ClInclude>
<ClInclude Include="core\Util\BinaryTree.h">
<Filter>Core\Util</Filter>
</ClInclude>
<ClInclude Include="core\Util\BlockVector.h">
<Filter>Core\Util</Filter>
</ClInclude>
<ClInclude Include="core\Util\BoolArray.h">
<Filter>Core\Util</Filter>
</ClInclude>
<ClInclude Include="core\Util\IndexIterator.h">
<Filter>Core\Util</Filter>
</ClInclude>
<ClInclude Include="core\Util\ObjectPool.h">
<Filter>Core\Util</Filter>
</ClInclude>
<ClInclude Include="core\Util\Path.h">
<Filter>Core\Util</Filter>
</ClInclude>
<ClInclude Include="core\Util\SmallDynamicArray.h">
<Filter>Core\Util</Filter>
</ClInclude>
<ClInclude Include="core\Voxelizer\BaseVoxelizer.h">
<Filter>Core\Voxelizer</Filter>
</ClInclude>
<ClInclude Include="core\Voxelizer\PVMVoxelizer.h">
<Filter>Core\Voxelizer</Filter>
</ClInclude>
<ClInclude Include="core\Voxelizer\TriangleMeshVoxelizer.h">
<Filter>Core\Voxelizer</Filter>
</ClInclude>
<ClInclude Include="core\Voxelizer\VoxelInfo.h">
<Filter>Core\Voxelizer</Filter>
</ClInclude>
<ClInclude Include="core\LightPath.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="scene\Material\MaterialLibraryPointer.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="scene\Material\MaterialPair.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="scene\Material\NearestFinder.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="scene\Material\SignedIntMaterial.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="scene\Material\SmallNormal.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="scene\Material\BaseMaterial.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="scene\Material\BitsMaterial.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="scene\Material\Block.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="scene\Material\BlockBasedMaterialLibrary.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="scene\Material\Color.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="scene\Material\ColorAndNormal.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="scene\Material\ColorAndNormalAndValue.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="scene\Material\ColorAndOpacity.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="scene\Material\ColorAndValue.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="scene\Material\ColorChannel.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="scene\Material\MaterialLibrary.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="scene\Material\MaterialQuantizer\ColorAndValueQuantizer.h">
<Filter>Scene\Material\MaterialQuantizer</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\IMaterialTexture.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\LeafMaterialMultiRootTree.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\MaterialLibraryMultiRootTree.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\MaterialLibraryTree.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\MaterialLibraryUniqueIndexTree.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\MaterialNode.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\MaterialTree.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\MultiRootTree.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\Node.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\NodeReplacementFinder.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\NodeSmall.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\Tree.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\UniqueIndexShiftTree.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\UniqueIndexTree.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\BaseTree.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\ChildMask.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\EdgeMaterialNode.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\HierarchicalColorsOnlyTree.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\HierarchicalMaterialMultiRoot.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\HierarchicalShiftingColoredTree.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\IAdditionalProperties.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\IBlockTexture.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="inc\pvm\ddsbase.h">
<Filter>Scene\PVM</Filter>
</ClInclude>
<ClInclude Include="inc\pvm\codebase.h">
<Filter>Scene\PVM</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\MultiRootBitsTree.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\ColorChannelMultiRootTree.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\PointLight.h">
<Filter>Scene</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp" />
<ClCompile Include="Renderer.cpp" />
<ClCompile Include="core\Controls.cpp">
<Filter>Core</Filter>
</ClCompile>
<ClCompile Include="scene\PNG.cpp">
<Filter>Scene</Filter>
</ClCompile>
<ClCompile Include="inc\lodepng\lodepng.cpp">
<Filter>Scene</Filter>
</ClCompile>
<ClCompile Include="shaders\ShaderLoader.cpp">
<Filter>Shaders</Filter>
</ClCompile>
<ClCompile Include="scene\ObjLoader.cpp">
<Filter>Scene</Filter>
</ClCompile>
<ClCompile Include="PropertyLoader.cpp" />
<ClCompile Include="core\Camera.cpp">
<Filter>Core</Filter>
</ClCompile>
<ClCompile Include="core\IntersectTests.cpp">
<Filter>Core</Filter>
</ClCompile>
<ClCompile Include="core\OctreeBuilder\MultiRootOctreeBuilder.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="core\OctreeBuilder\OctreeBuilder.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="core\OctreeBuilder\StandardOctreeBuilder.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="scene\DirectionalLight.cpp">
<Filter>Scene</Filter>
</ClCompile>
<ClCompile Include="core\OctreeBuilder\OctreeConverter.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="core\OctreeBuilder\OctreeLoader.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="scene\Material\MaterialQuantizer\ColorQuantizer\MaxErrorClusterer.cpp">
<Filter>Scene\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClCompile>
<ClCompile Include="scene\Material\MaterialQuantizer\ColorQuantizer\XiangCIELABClusterer.cpp">
<Filter>Scene\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClCompile>
<ClCompile Include="scene\Material\MaterialQuantizer\ColorQuantizer\XiangClusterer.cpp">
<Filter>Scene\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClCompile>
<ClCompile Include="scene\Material\MaterialQuantizer\ColorQuantizer\ColorBitCutter.cpp">
<Filter>Scene\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClCompile>
<ClCompile Include="core\ColorHelper.cpp">
<Filter>Core\Helpers</Filter>
</ClCompile>
<ClCompile Include="core\StringHelper.cpp">
<Filter>Core\Helpers</Filter>
</ClCompile>
<ClCompile Include="core\CameraPath.cpp">
<Filter>Core</Filter>
</ClCompile>
<ClCompile Include="core\OctreeBuilder\RandomOctreeBuilder.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="core\OctreeBuilder\MaterialLibraryMultiRootOctreeBuilder.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="core\OctreeBuilder\TreeTypeParser.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="core\OctreeBuilder\SettingsParser.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="scene\PoolBuilder\StandardPoolBuilder.cpp">
<Filter>Scene\PoolBuilder</Filter>
</ClCompile>
<ClCompile Include="scene\PoolBuilder\BaseTreePoolBuilder.cpp">
<Filter>Scene\PoolBuilder</Filter>
</ClCompile>
<ClCompile Include="scene\PoolBuilder\AdaptivePointerPoolBuilder.cpp">
<Filter>Scene\PoolBuilder</Filter>
</ClCompile>
<ClCompile Include="scene\PoolBuilder\VirtualNodePoolBuilder.cpp">
<Filter>Scene\PoolBuilder</Filter>
</ClCompile>
<ClCompile Include="core\PathHelper.cpp">
<Filter>Core\Helpers</Filter>
</ClCompile>
<ClCompile Include="core\OctreeBuilder\BaseOctreeBuilder.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="core\OctreeBuilder\ColorQuantizerFactory.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="core\OctreeBuilder\UniqueIndexShiftColoredOctreeBuilder.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="core\Util\Stopwatch.cpp">
<Filter>Core\Util</Filter>
</ClCompile>
<ClCompile Include="core\Util\BoolArray.cpp">
<Filter>Core\Util</Filter>
</ClCompile>
<ClCompile Include="core\Voxelizer\PVMVoxelizer.cpp">
<Filter>Core\Voxelizer</Filter>
</ClCompile>
<ClCompile Include="core\Voxelizer\TriangleMeshVoxelizer.cpp">
<Filter>Core\Voxelizer</Filter>
</ClCompile>
<ClCompile Include="core\LightPath.cpp">
<Filter>Core</Filter>
</ClCompile>
<ClCompile Include="scene\Material\Color.cpp">
<Filter>Scene\Material</Filter>
</ClCompile>
<ClCompile Include="scene\Material\ColorChannel.cpp">
<Filter>Scene\Material</Filter>
</ClCompile>
<ClCompile Include="scene\Octree\Node.cpp">
<Filter>Scene\Octree</Filter>
</ClCompile>
<ClCompile Include="scene\Octree\BaseTree.cpp">
<Filter>Scene\Octree</Filter>
</ClCompile>
<ClCompile Include="scene\Octree\HierarchicalColorsOnlyTree.cpp">
<Filter>Scene\Octree</Filter>
</ClCompile>
<ClCompile Include="scene\Octree\HierarchicalShiftingColoredTree.cpp">
<Filter>Scene\Octree</Filter>
</ClCompile>
<ClCompile Include="inc\pvm\ddsbase.cpp">
<Filter>Scene\PVM</Filter>
</ClCompile>
<ClCompile Include="scene\PointLight.cpp">
<Filter>Scene</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="shaders\Shader.frag">
<Filter>Shaders</Filter>
</None>
<None Include="shaders\Shader.vert">
<Filter>Shaders</Filter>
</None>
<None Include="shaders\DepthPeel.vert">
<Filter>Shaders</Filter>
</None>
<None Include="shaders\RenderTexture.frag">
<Filter>Shaders</Filter>
</None>
<None Include="shaders\DepthPeel.frag">
<Filter>Shaders</Filter>
</None>
<None Include="shaders\RenderTexture.vert">
<Filter>Shaders</Filter>
</None>
<None Include="shaders\StackRaytrace.frag">
<Filter>Shaders</Filter>
</None>
<None Include="shaders\Raytrace1.frag">
<Filter>Shaders</Filter>
</None>
<None Include="shaders\CombinedStackRaytrace.frag">
<Filter>Shaders</Filter>
</None>
<None Include="shaders\SSAO.frag">
<Filter>Shaders</Filter>
</None>
<None Include="shaders\SSAO2.frag">
<Filter>Shaders</Filter>
</None>
</ItemGroup>
<ItemGroup>
<Text Include="shaders\shader_properties.txt">
<Filter>Shaders</Filter>
</Text>
<Text Include="properties.txt" />
</ItemGroup>
</Project>

425
Research/Research.vcxproj Normal file
View File

@@ -0,0 +1,425 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.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="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release2|Win32">
<Configuration>Release2</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release2|x64">
<Configuration>Release2</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{22A4991F-1B7C-463F-BB36-AA539CA28F4A}</ProjectGuid>
<RootNamespace>Research</RootNamespace>
<ProjectName>Research</ProjectName>
<WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release2|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release2|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</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 Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<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>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release2|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release2|x64'" Label="PropertySheets">
<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'">
<LibraryPath>$(ProjectDir)\lib32;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LibraryPath>$(ProjectDir)\lib64;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LibraryPath>$(ProjectDir)\lib32;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release2|Win32'">
<LibraryPath>$(ProjectDir)\lib32;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LibraryPath>$(ProjectDir)\lib64;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release2|x64'">
<LibraryPath>$(ProjectDir)\lib64;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>glfw3.lib;opengl32.lib;glew32.lib;assimp.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalOptions>/VERBOSE:LIB %(AdditionalOptions)</AdditionalOptions>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>legacy_stdio_definitions.lib;glfw3.lib;opengl32.lib;glew32.lib;assimp.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalOptions>/VERBOSE:LIB %(AdditionalOptions)</AdditionalOptions>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Full</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<AdditionalDependencies>glfw3.lib;opengl32.lib;glew32.lib;assimp.lib;%(AdditionalDependencies)</AdditionalDependencies>
<Profile>true</Profile>
<AdditionalOptions>/VERBOSE:LIB %(AdditionalOptions)</AdditionalOptions>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release2|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Full</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<FavorSizeOrSpeed>Neither</FavorSizeOrSpeed>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>glfw3.lib;opengl32.lib;glew32.lib;assimp.lib;%(AdditionalDependencies)</AdditionalDependencies>
<Profile>true</Profile>
<AdditionalOptions>/VERBOSE:LIB %(AdditionalOptions)</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Full</Optimization>
<SDLCheck>true</SDLCheck>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<AdditionalDependencies>legacy_stdio_definitions.lib;glfw3.lib;opengl32.lib;glew32.lib;assimp.lib;%(AdditionalDependencies)</AdditionalDependencies>
<Profile>true</Profile>
<AdditionalOptions>/VERBOSE:LIB %(AdditionalOptions)</AdditionalOptions>
<OptimizeReferences>true</OptimizeReferences>
</Link>
<PostBuildEvent>
<Command>xcopy /C /Y "$(ProjectDir)lib64" "$(TargetDir.TrimEnd('\'))"</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release2|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Full</Optimization>
<SDLCheck>true</SDLCheck>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>legacy_stdio_definitions.lib;glfw3.lib;opengl32.lib;glew32.lib;assimp.lib;%(AdditionalDependencies)</AdditionalDependencies>
<Profile>true</Profile>
<AdditionalOptions>/VERBOSE:LIB %(AdditionalOptions)</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="core\BitHelper.h" />
<ClInclude Include="core\Camera.h" />
<ClInclude Include="core\CameraPath.h" />
<ClInclude Include="core\CollectionHelper.h" />
<ClInclude Include="core\ColorHelper.h" />
<ClInclude Include="core\Comparers.h" />
<ClInclude Include="core\CompileTimeArray.h" />
<ClInclude Include="core\Controls.h" />
<ClInclude Include="core\Defines.h" />
<ClInclude Include="core\Hashers.h" />
<ClInclude Include="core\IntersectTests.h" />
<ClInclude Include="core\LightPath.h" />
<ClInclude Include="core\MathHelper.h" />
<ClInclude Include="core\OctreeBuilder\BaseOctreeBuilder.h" />
<ClInclude Include="core\OctreeBuilder\ColorAndValueQuantizerFactory.h" />
<ClInclude Include="core\OctreeBuilder\ColorChannelMultiRootOctreeBuilder.h" />
<ClInclude Include="core\OctreeBuilder\ColorQuantizerFactory.h" />
<ClInclude Include="core\OctreeBuilder\CompressedTextureFactory.h" />
<ClInclude Include="core\OctreeBuilder\BaseMaterialOctreeBuilder.h" />
<ClInclude Include="core\OctreeBuilder\HierarchicalMaterialOctreeBuilder.h" />
<ClInclude Include="core\OctreeBuilder\MaterialLibraryMultiRootOctreeBuilder.h" />
<ClInclude Include="core\OctreeBuilder\MaterialMultiRootOctreeBuilder.h" />
<ClInclude Include="core\OctreeBuilder\MultiBitsMultiRootOctreeBuilder.h" />
<ClInclude Include="core\OctreeBuilder\MultiRootOctreeBuilder.h" />
<ClInclude Include="core\OctreeBuilder\NormalQuantizerFactory.h" />
<ClInclude Include="core\OctreeBuilder\OctreeBuilder.h" />
<ClInclude Include="core\OctreeBuilder\OctreeBuilderStatistics.h" />
<ClInclude Include="core\OctreeBuilder\OctreeConverter.h" />
<ClInclude Include="core\OctreeBuilder\OctreeLoader.h" />
<ClInclude Include="core\OctreeBuilder\PoolBuilderFactory.h" />
<ClInclude Include="core\OctreeBuilder\RandomOctreeBuilder.h" />
<ClInclude Include="core\OctreeBuilder\SettingsParser.h" />
<ClInclude Include="core\OctreeBuilder\BaseStandardOctreeBuilder.h" />
<ClInclude Include="core\OctreeBuilder\StandardOctreeBuilder.h" />
<ClInclude Include="core\OctreeBuilder\TreeTypeParser.h" />
<ClInclude Include="core\OctreeBuilder\UniqueIndexMaterialOctreeBuilder.h" />
<ClInclude Include="core\OctreeBuilder\UniqueIndexShiftColoredOctreeBuilder.h" />
<ClInclude Include="core\PathHelper.h" />
<ClInclude Include="core\Serializer.h" />
<ClInclude Include="core\StringHelper.h" />
<ClInclude Include="core\Util\BinaryTree.h" />
<ClInclude Include="core\Util\BlockVector.h" />
<ClInclude Include="core\Util\BoolArray.h" />
<ClInclude Include="core\Util\IndexIterator.h" />
<ClInclude Include="core\Util\ObjectPool.h" />
<ClInclude Include="core\Util\Path.h" />
<ClInclude Include="core\Util\SmallDynamicArray.h" />
<ClInclude Include="core\Util\Stopwatch.h" />
<ClInclude Include="core\Util\TransferFunction.h" />
<ClInclude Include="core\Voxelizer\BaseVoxelizer.h" />
<ClInclude Include="core\Voxelizer\PVMVoxelizer.h" />
<ClInclude Include="core\Voxelizer\TriangleMeshVoxelizer.h" />
<ClInclude Include="core\Voxelizer\VoxelInfo.h" />
<ClInclude Include="inc\lodepng\lodepng.h" />
<ClInclude Include="inc\pvm\codebase.h" />
<ClInclude Include="inc\pvm\ddsbase.h" />
<ClInclude Include="PropertyLoader.h" />
<ClInclude Include="Renderer.h" />
<ClInclude Include="scene\DirectionalLight.h" />
<ClInclude Include="scene\Material\MaterialQuantizer\NormalQuantizer.h" />
<ClInclude Include="scene\Octree\ColorChannelMultiRootTree.h" />
<ClInclude Include="scene\Octree\MultiRootBitsTree.h" />
<ClInclude Include="scene\PointLight.h" />
<ClInclude Include="scene\Material\BaseMaterial.h" />
<ClInclude Include="scene\Material\BitsMaterial.h" />
<ClInclude Include="scene\Material\Block.h" />
<ClInclude Include="scene\Material\BlockBasedMaterialLibrary.h" />
<ClInclude Include="scene\Material\Color.h" />
<ClInclude Include="scene\Material\ColorAndNormal.h" />
<ClInclude Include="scene\Material\ColorAndNormalAndValue.h" />
<ClInclude Include="scene\Material\ColorAndOpacity.h" />
<ClInclude Include="scene\Material\ColorAndValue.h" />
<ClInclude Include="scene\Material\ColorChannel.h" />
<ClInclude Include="scene\Material\MaterialLibrary.h" />
<ClInclude Include="scene\Material\MaterialLibraryPointer.h" />
<ClInclude Include="scene\Material\MaterialQuantizer\BaseQuantizer.h" />
<ClInclude Include="scene\Material\MaterialQuantizer\ColorAndValueQuantizer.h" />
<ClInclude Include="scene\Material\MaterialQuantizer\ColorQuantizer\BaseColorQuantizer.h" />
<ClInclude Include="scene\Material\MaterialQuantizer\ColorQuantizer\ColorBitCutter.h" />
<ClInclude Include="scene\Material\MaterialQuantizer\ColorQuantizer\MaxErrorClusterer.h" />
<ClInclude Include="scene\Material\MaterialQuantizer\ColorQuantizer\XiangCIELABClusterer.h" />
<ClInclude Include="scene\Material\MaterialQuantizer\ColorQuantizer\XiangClusterer.h" />
<ClInclude Include="scene\Material\NearestFinder.h" />
<ClInclude Include="scene\Material\SignedIntMaterial.h" />
<ClInclude Include="scene\Material\SmallNormal.h" />
<ClInclude Include="scene\Material\MaterialPair.h" />
<ClInclude Include="scene\ObjLoader.h" />
<ClInclude Include="scene\Octree\EdgeMaterialNode.h" />
<ClInclude Include="scene\Octree\HierarchicalMaterialMultiRoot.h" />
<ClInclude Include="scene\Octree\IAdditionalProperties.h" />
<ClInclude Include="scene\Octree\IBlockTexture.h" />
<ClInclude Include="scene\Octree\ChildMask.h" />
<ClInclude Include="scene\Octree\HierarchicalColorsOnlyTree.h" />
<ClInclude Include="scene\Octree\MaterialLibraryTree.h" />
<ClInclude Include="scene\Octree\HierarchicalShiftingColoredTree.h" />
<ClInclude Include="scene\Octree\BaseTree.h" />
<ClInclude Include="scene\Octree\LeafMaterialMultiRootTree.h" />
<ClInclude Include="scene\Octree\IMaterialTexture.h" />
<ClInclude Include="scene\Octree\MaterialLibraryMultiRootTree.h" />
<ClInclude Include="scene\Octree\MaterialLibraryUniqueIndexTree.h" />
<ClInclude Include="scene\Octree\MaterialTree.h" />
<ClInclude Include="scene\Octree\MultiRootTree.h" />
<ClInclude Include="scene\Octree\Node.h" />
<ClInclude Include="scene\Octree\NodeReplacementFinder.h" />
<ClInclude Include="scene\Octree\Tree.h" />
<ClInclude Include="scene\Octree\MaterialNode.h" />
<ClInclude Include="scene\Octree\UniqueIndexTree.h" />
<ClInclude Include="scene\Octree\UniqueIndexShiftTree.h" />
<ClInclude Include="scene\PNG.h" />
<ClInclude Include="scene\PoolBuilder\AdaptivePointerPoolBuilder.h" />
<ClInclude Include="scene\PoolBuilder\BasePoolBuilder.h" />
<ClInclude Include="scene\PoolBuilder\BaseTreePoolBuilder.h" />
<ClInclude Include="scene\PoolBuilder\OriginalPoolBuilder.h" />
<ClInclude Include="scene\PoolBuilder\StandardPoolBuilder.h" />
<ClInclude Include="scene\PoolBuilder\VirtualNodePoolBuilder.h" />
<ClInclude Include="scene\Scene.h" />
<ClInclude Include="scene\TextureCompressor\BasicTexture.h" />
<ClInclude Include="scene\TextureCompressor\BlockCompressedTexture.h" />
<ClInclude Include="scene\TextureCompressor\BlockHashers.h" />
<ClInclude Include="scene\TextureCompressor\CompressedTexture.h" />
<ClInclude Include="scene\TextureCompressor\DagBasedTexture.h" />
<ClInclude Include="scene\TextureCompressor\MultiRootBasedTexture.h" />
<ClInclude Include="scene\TextureCompressor\PaletteBlockTexture.h" />
<ClInclude Include="scene\TextureCompressor\TightlyPackedTexture.h" />
<ClInclude Include="shaders\ShaderLoader.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="core\Camera.cpp" />
<ClCompile Include="core\CameraPath.cpp" />
<ClCompile Include="core\ColorHelper.cpp" />
<ClCompile Include="core\Controls.cpp" />
<ClCompile Include="core\IntersectTests.cpp" />
<ClCompile Include="core\LightPath.cpp" />
<ClCompile Include="core\OctreeBuilder\BaseOctreeBuilder.cpp" />
<ClCompile Include="core\OctreeBuilder\ColorQuantizerFactory.cpp" />
<ClCompile Include="core\OctreeBuilder\MaterialLibraryMultiRootOctreeBuilder.cpp" />
<ClCompile Include="core\OctreeBuilder\MultiRootOctreeBuilder.cpp" />
<ClCompile Include="core\OctreeBuilder\NormalQuantizerFactory.cpp" />
<ClCompile Include="core\OctreeBuilder\OctreeBuilder.cpp" />
<ClCompile Include="core\OctreeBuilder\OctreeConverter.cpp" />
<ClCompile Include="core\OctreeBuilder\OctreeLoader.cpp" />
<ClCompile Include="core\OctreeBuilder\RandomOctreeBuilder.cpp" />
<ClCompile Include="core\OctreeBuilder\SettingsParser.cpp" />
<ClCompile Include="core\OctreeBuilder\StandardOctreeBuilder.cpp" />
<ClCompile Include="core\OctreeBuilder\TreeTypeParser.cpp" />
<ClCompile Include="core\OctreeBuilder\UniqueIndexShiftColoredOctreeBuilder.cpp" />
<ClCompile Include="core\PathHelper.cpp" />
<ClCompile Include="core\StringHelper.cpp" />
<ClCompile Include="core\Util\BoolArray.cpp" />
<ClCompile Include="core\Util\Stopwatch.cpp" />
<ClCompile Include="core\Voxelizer\PVMVoxelizer.cpp" />
<ClCompile Include="core\Voxelizer\TriangleMeshVoxelizer.cpp" />
<ClCompile Include="inc\lodepng\lodepng.cpp" />
<ClCompile Include="inc\pvm\ddsbase.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="PropertyLoader.cpp" />
<ClCompile Include="Renderer.cpp" />
<ClCompile Include="scene\DirectionalLight.cpp" />
<ClCompile Include="scene\Material\MaterialQuantizer\ColorQuantizer\BaseColorQuantizer.cpp" />
<ClCompile Include="scene\Material\MaterialQuantizer\NormalQuantizer.cpp" />
<ClCompile Include="scene\PointLight.cpp" />
<ClCompile Include="scene\Material\Color.cpp" />
<ClCompile Include="scene\Material\ColorChannel.cpp" />
<ClCompile Include="scene\Material\MaterialQuantizer\ColorQuantizer\ColorBitCutter.cpp" />
<ClCompile Include="scene\Material\MaterialQuantizer\ColorQuantizer\MaxErrorClusterer.cpp" />
<ClCompile Include="scene\Material\MaterialQuantizer\ColorQuantizer\XiangCIELABClusterer.cpp" />
<ClCompile Include="scene\Material\MaterialQuantizer\ColorQuantizer\XiangClusterer.cpp" />
<ClCompile Include="scene\ObjLoader.cpp" />
<ClCompile Include="scene\Octree\BaseTree.cpp" />
<ClCompile Include="scene\Octree\HierarchicalColorsOnlyTree.cpp" />
<ClCompile Include="scene\Octree\HierarchicalShiftingColoredTree.cpp" />
<ClCompile Include="scene\Octree\Node.cpp" />
<ClCompile Include="scene\PNG.cpp" />
<ClCompile Include="scene\PoolBuilder\AdaptivePointerPoolBuilder.cpp" />
<ClCompile Include="scene\PoolBuilder\BaseTreePoolBuilder.cpp" />
<ClCompile Include="scene\PoolBuilder\StandardPoolBuilder.cpp" />
<ClCompile Include="scene\PoolBuilder\VirtualNodePoolBuilder.cpp" />
<ClCompile Include="shaders\ShaderLoader.cpp" />
</ItemGroup>
<ItemGroup>
<None Include="shaders\CombinedStackRaytrace.frag" />
<None Include="shaders\DepthPeel.frag" />
<None Include="shaders\DepthPeel.vert" />
<None Include="shaders\GI.frag" />
<None Include="shaders\Raytrace1.frag" />
<None Include="shaders\RenderTexture.vert" />
<None Include="shaders\RenderTexture.frag" />
<None Include="shaders\Shader.frag" />
<None Include="shaders\Shader.vert" />
<None Include="shaders\SSAO.frag" />
<None Include="shaders\SSAO2.frag" />
<None Include="shaders\SSDS.frag" />
<None Include="shaders\StackRaytrace.frag" />
</ItemGroup>
<ItemGroup>
<Text Include="properties.txt" />
<Text Include="Readme.txt" />
<Text Include="shaders\shader_properties.txt" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,618 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Core">
<UniqueIdentifier>{633bca08-629d-415e-9025-d35a00ed864e}</UniqueIdentifier>
</Filter>
<Filter Include="Scene">
<UniqueIdentifier>{abb43287-8c7b-4c8b-a210-7efeab2d8679}</UniqueIdentifier>
</Filter>
<Filter Include="Core\OctreeBuilder">
<UniqueIdentifier>{a65dfa3d-c828-4996-aa18-119e8a46e50f}</UniqueIdentifier>
</Filter>
<Filter Include="Scene\Octree">
<UniqueIdentifier>{971f6a5b-d390-4b1f-ade3-9e66b60e384b}</UniqueIdentifier>
</Filter>
<Filter Include="Scene\Material">
<UniqueIdentifier>{e89d5220-655b-4777-8d9f-eadfd219b6a4}</UniqueIdentifier>
</Filter>
<Filter Include="Scene\Material\MaterialQuantizer">
<UniqueIdentifier>{e1796e23-6f5f-4851-b9a8-c38bbd2c6d2f}</UniqueIdentifier>
</Filter>
<Filter Include="Scene\Material\MaterialQuantizer\ColorQuantizer">
<UniqueIdentifier>{11b192c3-922f-4949-a591-e5790c04cdfa}</UniqueIdentifier>
</Filter>
<Filter Include="Scene\TextureCompressor">
<UniqueIdentifier>{a62fdf46-78ed-475b-88d0-a2bab6ed5ce6}</UniqueIdentifier>
</Filter>
<Filter Include="Core\Helpers">
<UniqueIdentifier>{dbe53c3a-dd4d-4f30-9c91-4d0611be2800}</UniqueIdentifier>
</Filter>
<Filter Include="Core\Util">
<UniqueIdentifier>{4339393f-4085-4c33-8666-bcca22eb2796}</UniqueIdentifier>
</Filter>
<Filter Include="Scene\PoolBuilder">
<UniqueIdentifier>{ef901ea6-d046-4226-aba0-1bf6cd6042a8}</UniqueIdentifier>
</Filter>
<Filter Include="Scene\PVM">
<UniqueIdentifier>{43a609b0-7d29-4c83-bb30-bdf483b21a43}</UniqueIdentifier>
</Filter>
<Filter Include="Core\Voxelizer">
<UniqueIdentifier>{dc495dc0-adec-4578-a785-444a19ed84e8}</UniqueIdentifier>
</Filter>
<Filter Include="Shaders">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Renderer.h" />
<ClInclude Include="core\Controls.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="core\Defines.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="scene\ObjLoader.h">
<Filter>Scene</Filter>
</ClInclude>
<ClInclude Include="scene\PNG.h">
<Filter>Scene</Filter>
</ClInclude>
<ClInclude Include="inc\lodepng\lodepng.h">
<Filter>Scene</Filter>
</ClInclude>
<ClInclude Include="shaders\ShaderLoader.h">
<Filter>Shaders</Filter>
</ClInclude>
<ClInclude Include="scene\Scene.h">
<Filter>Scene</Filter>
</ClInclude>
<ClInclude Include="PropertyLoader.h" />
<ClInclude Include="core\Camera.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="core\IntersectTests.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\BaseOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\MultiRootOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\OctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\OctreeBuilderStatistics.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\StandardOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="scene\DirectionalLight.h">
<Filter>Scene</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\Node.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\ColorChannelMultiRootOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\MaterialMultiRootOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\MultiBitsMultiRootOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="core\Hashers.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="core\Comparers.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\OctreeConverter.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\OctreeLoader.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\MaterialNode.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\CompressedTextureFactory.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\ChildMask.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Material\MaterialQuantizer\ColorQuantizer\BaseColorQuantizer.h">
<Filter>Scene\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClInclude>
<ClInclude Include="scene\Material\MaterialQuantizer\ColorQuantizer\MaxErrorClusterer.h">
<Filter>Scene\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClInclude>
<ClInclude Include="scene\Material\MaterialQuantizer\ColorQuantizer\XiangCIELABClusterer.h">
<Filter>Scene\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClInclude>
<ClInclude Include="scene\Material\MaterialQuantizer\ColorQuantizer\XiangClusterer.h">
<Filter>Scene\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClInclude>
<ClInclude Include="scene\Material\BaseMaterial.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="scene\Material\BitsMaterial.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="scene\Material\Block.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="scene\Material\Color.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="scene\Material\ColorChannel.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="scene\Material\MaterialLibrary.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="scene\Material\MaterialLibraryPointer.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\IBlockTexture.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\IMaterialTexture.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Material\MaterialQuantizer\ColorQuantizer\ColorBitCutter.h">
<Filter>Scene\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClInclude>
<ClInclude Include="core\BitHelper.h">
<Filter>Core\Helpers</Filter>
</ClInclude>
<ClInclude Include="core\ColorHelper.h">
<Filter>Core\Helpers</Filter>
</ClInclude>
<ClInclude Include="core\StringHelper.h">
<Filter>Core\Helpers</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\IAdditionalProperties.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="core\CameraPath.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="core\CollectionHelper.h">
<Filter>Core\Helpers</Filter>
</ClInclude>
<ClInclude Include="core\MathHelper.h">
<Filter>Core\Helpers</Filter>
</ClInclude>
<ClInclude Include="core\CompileTimeArray.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="scene\TextureCompressor\BasicTexture.h">
<Filter>Scene\TextureCompressor</Filter>
</ClInclude>
<ClInclude Include="scene\TextureCompressor\BlockCompressedTexture.h">
<Filter>Scene\TextureCompressor</Filter>
</ClInclude>
<ClInclude Include="scene\TextureCompressor\BlockHashers.h">
<Filter>Scene\TextureCompressor</Filter>
</ClInclude>
<ClInclude Include="scene\TextureCompressor\CompressedTexture.h">
<Filter>Scene\TextureCompressor</Filter>
</ClInclude>
<ClInclude Include="scene\TextureCompressor\TightlyPackedTexture.h">
<Filter>Scene\TextureCompressor</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\MaterialTree.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\RandomOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\LeafMaterialMultiRootTree.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\HierarchicalMaterialMultiRoot.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\MaterialLibraryMultiRootTree.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\MaterialLibraryMultiRootOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="core\Serializer.h">
<Filter>Core\Helpers</Filter>
</ClInclude>
<ClInclude Include="core\Util\Stopwatch.h">
<Filter>Core\Util</Filter>
</ClInclude>
<ClInclude Include="core\Util\BoolArray.h">
<Filter>Core\Util</Filter>
</ClInclude>
<ClInclude Include="scene\Material\BlockBasedMaterialLibrary.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="core\Util\BinaryTree.h">
<Filter>Core\Util</Filter>
</ClInclude>
<ClInclude Include="scene\TextureCompressor\DagBasedTexture.h">
<Filter>Scene\TextureCompressor</Filter>
</ClInclude>
<ClInclude Include="scene\TextureCompressor\MultiRootBasedTexture.h">
<Filter>Scene\TextureCompressor</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\TreeTypeParser.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\SettingsParser.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="scene\PoolBuilder\BasePoolBuilder.h">
<Filter>Scene\PoolBuilder</Filter>
</ClInclude>
<ClInclude Include="scene\PoolBuilder\StandardPoolBuilder.h">
<Filter>Scene\PoolBuilder</Filter>
</ClInclude>
<ClInclude Include="scene\PoolBuilder\BaseTreePoolBuilder.h">
<Filter>Scene\PoolBuilder</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\PoolBuilderFactory.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="scene\PoolBuilder\OriginalPoolBuilder.h">
<Filter>Scene\PoolBuilder</Filter>
</ClInclude>
<ClInclude Include="scene\PoolBuilder\AdaptivePointerPoolBuilder.h">
<Filter>Scene\PoolBuilder</Filter>
</ClInclude>
<ClInclude Include="scene\PoolBuilder\VirtualNodePoolBuilder.h">
<Filter>Scene\PoolBuilder</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\NodeReplacementFinder.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\TextureCompressor\PaletteBlockTexture.h">
<Filter>Scene\TextureCompressor</Filter>
</ClInclude>
<ClInclude Include="scene\Material\SignedIntMaterial.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\UniqueIndexShiftColoredOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="scene\Material\SmallNormal.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\BaseMaterialOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\BaseStandardOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\HierarchicalMaterialOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\UniqueIndexMaterialOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="scene\Material\MaterialQuantizer\BaseQuantizer.h">
<Filter>Scene\Material\MaterialQuantizer</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\ColorQuantizerFactory.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="inc\pvm\ddsbase.h">
<Filter>Scene\PVM</Filter>
</ClInclude>
<ClInclude Include="inc\pvm\codebase.h">
<Filter>Scene\PVM</Filter>
</ClInclude>
<ClInclude Include="core\Util\TransferFunction.h">
<Filter>Core\Util</Filter>
</ClInclude>
<ClInclude Include="core\Voxelizer\TriangleMeshVoxelizer.h">
<Filter>Core\Voxelizer</Filter>
</ClInclude>
<ClInclude Include="core\Voxelizer\VoxelInfo.h">
<Filter>Core\Voxelizer</Filter>
</ClInclude>
<ClInclude Include="core\Voxelizer\PVMVoxelizer.h">
<Filter>Core\Voxelizer</Filter>
</ClInclude>
<ClInclude Include="core\PathHelper.h">
<Filter>Core\Helpers</Filter>
</ClInclude>
<ClInclude Include="scene\Material\ColorAndValue.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="scene\Material\ColorAndNormal.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="scene\Material\MaterialQuantizer\ColorAndValueQuantizer.h">
<Filter>Scene\Material\MaterialQuantizer</Filter>
</ClInclude>
<ClInclude Include="scene\Material\MaterialPair.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="scene\Material\NearestFinder.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="scene\Material\ColorAndNormalAndValue.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="scene\Material\ColorAndOpacity.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\ColorAndValueQuantizerFactory.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\Tree.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\BaseTree.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\MultiRootTree.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\EdgeMaterialNode.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\HierarchicalShiftingColoredTree.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\HierarchicalColorsOnlyTree.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\MaterialLibraryTree.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\UniqueIndexTree.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\UniqueIndexShiftTree.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\MaterialLibraryUniqueIndexTree.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="core\Voxelizer\BaseVoxelizer.h">
<Filter>Core\Voxelizer</Filter>
</ClInclude>
<ClInclude Include="core\Util\ObjectPool.h">
<Filter>Core\Util</Filter>
</ClInclude>
<ClInclude Include="core\Util\SmallDynamicArray.h">
<Filter>Core\Util</Filter>
</ClInclude>
<ClInclude Include="core\Util\BlockVector.h">
<Filter>Core\Util</Filter>
</ClInclude>
<ClInclude Include="core\Util\IndexIterator.h">
<Filter>Core\Util</Filter>
</ClInclude>
<ClInclude Include="core\Util\Path.h">
<Filter>Core\Util</Filter>
</ClInclude>
<ClInclude Include="scene\PointLight.h">
<Filter>Scene</Filter>
</ClInclude>
<ClInclude Include="core\LightPath.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\MultiRootBitsTree.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\ColorChannelMultiRootTree.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Material\MaterialQuantizer\NormalQuantizer.h">
<Filter>Scene\Material\MaterialQuantizer</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\NormalQuantizerFactory.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp" />
<ClCompile Include="Renderer.cpp" />
<ClCompile Include="core\Controls.cpp">
<Filter>Core</Filter>
</ClCompile>
<ClCompile Include="scene\PNG.cpp">
<Filter>Scene</Filter>
</ClCompile>
<ClCompile Include="inc\lodepng\lodepng.cpp">
<Filter>Scene</Filter>
</ClCompile>
<ClCompile Include="shaders\ShaderLoader.cpp">
<Filter>Shaders</Filter>
</ClCompile>
<ClCompile Include="scene\ObjLoader.cpp">
<Filter>Scene</Filter>
</ClCompile>
<ClCompile Include="PropertyLoader.cpp" />
<ClCompile Include="core\Camera.cpp">
<Filter>Core</Filter>
</ClCompile>
<ClCompile Include="core\IntersectTests.cpp">
<Filter>Core</Filter>
</ClCompile>
<ClCompile Include="core\OctreeBuilder\MultiRootOctreeBuilder.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="core\OctreeBuilder\OctreeBuilder.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="core\OctreeBuilder\StandardOctreeBuilder.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="scene\DirectionalLight.cpp">
<Filter>Scene</Filter>
</ClCompile>
<ClCompile Include="scene\Octree\Node.cpp">
<Filter>Scene\Octree</Filter>
</ClCompile>
<ClCompile Include="core\OctreeBuilder\OctreeConverter.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="core\OctreeBuilder\OctreeLoader.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="scene\Material\MaterialQuantizer\ColorQuantizer\MaxErrorClusterer.cpp">
<Filter>Scene\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClCompile>
<ClCompile Include="scene\Material\MaterialQuantizer\ColorQuantizer\XiangCIELABClusterer.cpp">
<Filter>Scene\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClCompile>
<ClCompile Include="scene\Material\MaterialQuantizer\ColorQuantizer\XiangClusterer.cpp">
<Filter>Scene\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClCompile>
<ClCompile Include="scene\Material\Color.cpp">
<Filter>Scene\Material</Filter>
</ClCompile>
<ClCompile Include="scene\Material\ColorChannel.cpp">
<Filter>Scene\Material</Filter>
</ClCompile>
<ClCompile Include="scene\Material\MaterialQuantizer\ColorQuantizer\ColorBitCutter.cpp">
<Filter>Scene\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClCompile>
<ClCompile Include="core\ColorHelper.cpp">
<Filter>Core\Helpers</Filter>
</ClCompile>
<ClCompile Include="core\StringHelper.cpp">
<Filter>Core\Helpers</Filter>
</ClCompile>
<ClCompile Include="core\CameraPath.cpp">
<Filter>Core</Filter>
</ClCompile>
<ClCompile Include="core\OctreeBuilder\RandomOctreeBuilder.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="core\OctreeBuilder\MaterialLibraryMultiRootOctreeBuilder.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="core\Util\Stopwatch.cpp">
<Filter>Core\Util</Filter>
</ClCompile>
<ClCompile Include="core\Util\BoolArray.cpp">
<Filter>Core\Util</Filter>
</ClCompile>
<ClCompile Include="core\OctreeBuilder\TreeTypeParser.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="core\OctreeBuilder\SettingsParser.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="scene\PoolBuilder\StandardPoolBuilder.cpp">
<Filter>Scene\PoolBuilder</Filter>
</ClCompile>
<ClCompile Include="scene\PoolBuilder\BaseTreePoolBuilder.cpp">
<Filter>Scene\PoolBuilder</Filter>
</ClCompile>
<ClCompile Include="scene\PoolBuilder\AdaptivePointerPoolBuilder.cpp">
<Filter>Scene\PoolBuilder</Filter>
</ClCompile>
<ClCompile Include="scene\PoolBuilder\VirtualNodePoolBuilder.cpp">
<Filter>Scene\PoolBuilder</Filter>
</ClCompile>
<ClCompile Include="core\OctreeBuilder\UniqueIndexShiftColoredOctreeBuilder.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="core\OctreeBuilder\ColorQuantizerFactory.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="inc\pvm\ddsbase.cpp">
<Filter>Scene\PVM</Filter>
</ClCompile>
<ClCompile Include="core\Voxelizer\TriangleMeshVoxelizer.cpp">
<Filter>Core\Voxelizer</Filter>
</ClCompile>
<ClCompile Include="core\Voxelizer\PVMVoxelizer.cpp">
<Filter>Core\Voxelizer</Filter>
</ClCompile>
<ClCompile Include="core\PathHelper.cpp">
<Filter>Core\Helpers</Filter>
</ClCompile>
<ClCompile Include="scene\Octree\HierarchicalShiftingColoredTree.cpp">
<Filter>Scene\Octree</Filter>
</ClCompile>
<ClCompile Include="scene\Octree\HierarchicalColorsOnlyTree.cpp">
<Filter>Scene\Octree</Filter>
</ClCompile>
<ClCompile Include="scene\Octree\BaseTree.cpp">
<Filter>Scene\Octree</Filter>
</ClCompile>
<ClCompile Include="core\OctreeBuilder\BaseOctreeBuilder.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="scene\PointLight.cpp">
<Filter>Scene</Filter>
</ClCompile>
<ClCompile Include="core\LightPath.cpp">
<Filter>Core</Filter>
</ClCompile>
<ClCompile Include="scene\Material\MaterialQuantizer\ColorQuantizer\BaseColorQuantizer.cpp">
<Filter>Scene\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClCompile>
<ClCompile Include="scene\Material\MaterialQuantizer\NormalQuantizer.cpp">
<Filter>Scene\Material\MaterialQuantizer</Filter>
</ClCompile>
<ClCompile Include="core\OctreeBuilder\NormalQuantizerFactory.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="shaders\Shader.frag">
<Filter>Shaders</Filter>
</None>
<None Include="shaders\Shader.vert">
<Filter>Shaders</Filter>
</None>
<None Include="shaders\DepthPeel.vert">
<Filter>Shaders</Filter>
</None>
<None Include="shaders\RenderTexture.frag">
<Filter>Shaders</Filter>
</None>
<None Include="shaders\DepthPeel.frag">
<Filter>Shaders</Filter>
</None>
<None Include="shaders\RenderTexture.vert">
<Filter>Shaders</Filter>
</None>
<None Include="shaders\StackRaytrace.frag">
<Filter>Shaders</Filter>
</None>
<None Include="shaders\Raytrace1.frag">
<Filter>Shaders</Filter>
</None>
<None Include="shaders\CombinedStackRaytrace.frag">
<Filter>Shaders</Filter>
</None>
<None Include="shaders\SSAO.frag">
<Filter>Shaders</Filter>
</None>
<None Include="shaders\SSAO2.frag">
<Filter>Shaders</Filter>
</None>
<None Include="shaders\GI.frag">
<Filter>Shaders</Filter>
</None>
<None Include="shaders\SSDS.frag">
<Filter>Shaders</Filter>
</None>
</ItemGroup>
<ItemGroup>
<Text Include="shaders\shader_properties.txt">
<Filter>Shaders</Filter>
</Text>
<Text Include="properties.txt" />
<Text Include="Readme.txt" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,618 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Core">
<UniqueIdentifier>{633bca08-629d-415e-9025-d35a00ed864e}</UniqueIdentifier>
</Filter>
<Filter Include="Scene">
<UniqueIdentifier>{abb43287-8c7b-4c8b-a210-7efeab2d8679}</UniqueIdentifier>
</Filter>
<Filter Include="Core\OctreeBuilder">
<UniqueIdentifier>{a65dfa3d-c828-4996-aa18-119e8a46e50f}</UniqueIdentifier>
</Filter>
<Filter Include="Scene\Octree">
<UniqueIdentifier>{971f6a5b-d390-4b1f-ade3-9e66b60e384b}</UniqueIdentifier>
</Filter>
<Filter Include="Scene\Material">
<UniqueIdentifier>{e89d5220-655b-4777-8d9f-eadfd219b6a4}</UniqueIdentifier>
</Filter>
<Filter Include="Scene\Material\MaterialQuantizer">
<UniqueIdentifier>{e1796e23-6f5f-4851-b9a8-c38bbd2c6d2f}</UniqueIdentifier>
</Filter>
<Filter Include="Scene\Material\MaterialQuantizer\ColorQuantizer">
<UniqueIdentifier>{11b192c3-922f-4949-a591-e5790c04cdfa}</UniqueIdentifier>
</Filter>
<Filter Include="Scene\TextureCompressor">
<UniqueIdentifier>{a62fdf46-78ed-475b-88d0-a2bab6ed5ce6}</UniqueIdentifier>
</Filter>
<Filter Include="Core\Helpers">
<UniqueIdentifier>{dbe53c3a-dd4d-4f30-9c91-4d0611be2800}</UniqueIdentifier>
</Filter>
<Filter Include="Core\Util">
<UniqueIdentifier>{4339393f-4085-4c33-8666-bcca22eb2796}</UniqueIdentifier>
</Filter>
<Filter Include="Scene\PoolBuilder">
<UniqueIdentifier>{ef901ea6-d046-4226-aba0-1bf6cd6042a8}</UniqueIdentifier>
</Filter>
<Filter Include="Scene\PVM">
<UniqueIdentifier>{43a609b0-7d29-4c83-bb30-bdf483b21a43}</UniqueIdentifier>
</Filter>
<Filter Include="Core\Voxelizer">
<UniqueIdentifier>{dc495dc0-adec-4578-a785-444a19ed84e8}</UniqueIdentifier>
</Filter>
<Filter Include="Shaders">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Renderer.h" />
<ClInclude Include="core\Controls.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="core\Defines.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="scene\ObjLoader.h">
<Filter>Scene</Filter>
</ClInclude>
<ClInclude Include="scene\PNG.h">
<Filter>Scene</Filter>
</ClInclude>
<ClInclude Include="inc\lodepng\lodepng.h">
<Filter>Scene</Filter>
</ClInclude>
<ClInclude Include="shaders\ShaderLoader.h">
<Filter>Shaders</Filter>
</ClInclude>
<ClInclude Include="scene\Scene.h">
<Filter>Scene</Filter>
</ClInclude>
<ClInclude Include="PropertyLoader.h" />
<ClInclude Include="core\Camera.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="core\IntersectTests.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\BaseOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\MultiRootOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\OctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\OctreeBuilderStatistics.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\StandardOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="scene\DirectionalLight.h">
<Filter>Scene</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\Node.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\ColorChannelMultiRootOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\MaterialMultiRootOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\MultiBitsMultiRootOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="core\Hashers.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="core\Comparers.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\OctreeConverter.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\OctreeLoader.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\MaterialNode.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\CompressedTextureFactory.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\ChildMask.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Material\MaterialQuantizer\ColorQuantizer\BaseColorQuantizer.h">
<Filter>Scene\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClInclude>
<ClInclude Include="scene\Material\MaterialQuantizer\ColorQuantizer\MaxErrorClusterer.h">
<Filter>Scene\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClInclude>
<ClInclude Include="scene\Material\MaterialQuantizer\ColorQuantizer\XiangCIELABClusterer.h">
<Filter>Scene\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClInclude>
<ClInclude Include="scene\Material\MaterialQuantizer\ColorQuantizer\XiangClusterer.h">
<Filter>Scene\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClInclude>
<ClInclude Include="scene\Material\BaseMaterial.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="scene\Material\BitsMaterial.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="scene\Material\Block.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="scene\Material\Color.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="scene\Material\ColorChannel.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="scene\Material\MaterialLibrary.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="scene\Material\MaterialLibraryPointer.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\IBlockTexture.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\IMaterialTexture.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Material\MaterialQuantizer\ColorQuantizer\ColorBitCutter.h">
<Filter>Scene\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClInclude>
<ClInclude Include="core\BitHelper.h">
<Filter>Core\Helpers</Filter>
</ClInclude>
<ClInclude Include="core\ColorHelper.h">
<Filter>Core\Helpers</Filter>
</ClInclude>
<ClInclude Include="core\StringHelper.h">
<Filter>Core\Helpers</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\IAdditionalProperties.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="core\CameraPath.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="core\CollectionHelper.h">
<Filter>Core\Helpers</Filter>
</ClInclude>
<ClInclude Include="core\MathHelper.h">
<Filter>Core\Helpers</Filter>
</ClInclude>
<ClInclude Include="core\CompileTimeArray.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="scene\TextureCompressor\BasicTexture.h">
<Filter>Scene\TextureCompressor</Filter>
</ClInclude>
<ClInclude Include="scene\TextureCompressor\BlockCompressedTexture.h">
<Filter>Scene\TextureCompressor</Filter>
</ClInclude>
<ClInclude Include="scene\TextureCompressor\BlockHashers.h">
<Filter>Scene\TextureCompressor</Filter>
</ClInclude>
<ClInclude Include="scene\TextureCompressor\CompressedTexture.h">
<Filter>Scene\TextureCompressor</Filter>
</ClInclude>
<ClInclude Include="scene\TextureCompressor\TightlyPackedTexture.h">
<Filter>Scene\TextureCompressor</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\MaterialTree.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\RandomOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\LeafMaterialMultiRootTree.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\HierarchicalMaterialMultiRoot.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\MaterialLibraryMultiRootTree.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\MaterialLibraryMultiRootOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="core\Serializer.h">
<Filter>Core\Helpers</Filter>
</ClInclude>
<ClInclude Include="core\Util\Stopwatch.h">
<Filter>Core\Util</Filter>
</ClInclude>
<ClInclude Include="core\Util\BoolArray.h">
<Filter>Core\Util</Filter>
</ClInclude>
<ClInclude Include="scene\Material\BlockBasedMaterialLibrary.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="core\Util\BinaryTree.h">
<Filter>Core\Util</Filter>
</ClInclude>
<ClInclude Include="scene\TextureCompressor\DagBasedTexture.h">
<Filter>Scene\TextureCompressor</Filter>
</ClInclude>
<ClInclude Include="scene\TextureCompressor\MultiRootBasedTexture.h">
<Filter>Scene\TextureCompressor</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\TreeTypeParser.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\SettingsParser.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="scene\PoolBuilder\BasePoolBuilder.h">
<Filter>Scene\PoolBuilder</Filter>
</ClInclude>
<ClInclude Include="scene\PoolBuilder\StandardPoolBuilder.h">
<Filter>Scene\PoolBuilder</Filter>
</ClInclude>
<ClInclude Include="scene\PoolBuilder\BaseTreePoolBuilder.h">
<Filter>Scene\PoolBuilder</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\PoolBuilderFactory.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="scene\PoolBuilder\OriginalPoolBuilder.h">
<Filter>Scene\PoolBuilder</Filter>
</ClInclude>
<ClInclude Include="scene\PoolBuilder\AdaptivePointerPoolBuilder.h">
<Filter>Scene\PoolBuilder</Filter>
</ClInclude>
<ClInclude Include="scene\PoolBuilder\VirtualNodePoolBuilder.h">
<Filter>Scene\PoolBuilder</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\NodeReplacementFinder.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\TextureCompressor\PaletteBlockTexture.h">
<Filter>Scene\TextureCompressor</Filter>
</ClInclude>
<ClInclude Include="scene\Material\SignedIntMaterial.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\UniqueIndexShiftColoredOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="scene\Material\SmallNormal.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\BaseMaterialOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\BaseStandardOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\HierarchicalMaterialOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\UniqueIndexMaterialOctreeBuilder.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="scene\Material\MaterialQuantizer\BaseQuantizer.h">
<Filter>Scene\Material\MaterialQuantizer</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\ColorQuantizerFactory.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="inc\pvm\ddsbase.h">
<Filter>Scene\PVM</Filter>
</ClInclude>
<ClInclude Include="inc\pvm\codebase.h">
<Filter>Scene\PVM</Filter>
</ClInclude>
<ClInclude Include="core\Util\TransferFunction.h">
<Filter>Core\Util</Filter>
</ClInclude>
<ClInclude Include="core\Voxelizer\TriangleMeshVoxelizer.h">
<Filter>Core\Voxelizer</Filter>
</ClInclude>
<ClInclude Include="core\Voxelizer\VoxelInfo.h">
<Filter>Core\Voxelizer</Filter>
</ClInclude>
<ClInclude Include="core\Voxelizer\PVMVoxelizer.h">
<Filter>Core\Voxelizer</Filter>
</ClInclude>
<ClInclude Include="core\PathHelper.h">
<Filter>Core\Helpers</Filter>
</ClInclude>
<ClInclude Include="scene\Material\ColorAndValue.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="scene\Material\ColorAndNormal.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="scene\Material\MaterialQuantizer\ColorAndValueQuantizer.h">
<Filter>Scene\Material\MaterialQuantizer</Filter>
</ClInclude>
<ClInclude Include="scene\Material\MaterialPair.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="scene\Material\NearestFinder.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="scene\Material\ColorAndNormalAndValue.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="scene\Material\ColorAndOpacity.h">
<Filter>Scene\Material</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\ColorAndValueQuantizerFactory.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\Tree.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\BaseTree.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\MultiRootTree.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\EdgeMaterialNode.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\HierarchicalShiftingColoredTree.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\HierarchicalColorsOnlyTree.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\MaterialLibraryTree.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\UniqueIndexTree.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\UniqueIndexShiftTree.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\MaterialLibraryUniqueIndexTree.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="core\Voxelizer\BaseVoxelizer.h">
<Filter>Core\Voxelizer</Filter>
</ClInclude>
<ClInclude Include="core\Util\ObjectPool.h">
<Filter>Core\Util</Filter>
</ClInclude>
<ClInclude Include="core\Util\SmallDynamicArray.h">
<Filter>Core\Util</Filter>
</ClInclude>
<ClInclude Include="core\Util\BlockVector.h">
<Filter>Core\Util</Filter>
</ClInclude>
<ClInclude Include="core\Util\IndexIterator.h">
<Filter>Core\Util</Filter>
</ClInclude>
<ClInclude Include="core\Util\Path.h">
<Filter>Core\Util</Filter>
</ClInclude>
<ClInclude Include="scene\PointLight.h">
<Filter>Scene</Filter>
</ClInclude>
<ClInclude Include="core\LightPath.h">
<Filter>Core</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\MultiRootBitsTree.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Octree\ColorChannelMultiRootTree.h">
<Filter>Scene\Octree</Filter>
</ClInclude>
<ClInclude Include="scene\Material\MaterialQuantizer\NormalQuantizer.h">
<Filter>Scene\Material\MaterialQuantizer</Filter>
</ClInclude>
<ClInclude Include="core\OctreeBuilder\NormalQuantizerFactory.h">
<Filter>Core\OctreeBuilder</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp" />
<ClCompile Include="Renderer.cpp" />
<ClCompile Include="core\Controls.cpp">
<Filter>Core</Filter>
</ClCompile>
<ClCompile Include="scene\PNG.cpp">
<Filter>Scene</Filter>
</ClCompile>
<ClCompile Include="inc\lodepng\lodepng.cpp">
<Filter>Scene</Filter>
</ClCompile>
<ClCompile Include="shaders\ShaderLoader.cpp">
<Filter>Shaders</Filter>
</ClCompile>
<ClCompile Include="scene\ObjLoader.cpp">
<Filter>Scene</Filter>
</ClCompile>
<ClCompile Include="PropertyLoader.cpp" />
<ClCompile Include="core\Camera.cpp">
<Filter>Core</Filter>
</ClCompile>
<ClCompile Include="core\IntersectTests.cpp">
<Filter>Core</Filter>
</ClCompile>
<ClCompile Include="core\OctreeBuilder\MultiRootOctreeBuilder.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="core\OctreeBuilder\OctreeBuilder.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="core\OctreeBuilder\StandardOctreeBuilder.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="scene\DirectionalLight.cpp">
<Filter>Scene</Filter>
</ClCompile>
<ClCompile Include="scene\Octree\Node.cpp">
<Filter>Scene\Octree</Filter>
</ClCompile>
<ClCompile Include="core\OctreeBuilder\OctreeConverter.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="core\OctreeBuilder\OctreeLoader.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="scene\Material\MaterialQuantizer\ColorQuantizer\MaxErrorClusterer.cpp">
<Filter>Scene\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClCompile>
<ClCompile Include="scene\Material\MaterialQuantizer\ColorQuantizer\XiangCIELABClusterer.cpp">
<Filter>Scene\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClCompile>
<ClCompile Include="scene\Material\MaterialQuantizer\ColorQuantizer\XiangClusterer.cpp">
<Filter>Scene\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClCompile>
<ClCompile Include="scene\Material\Color.cpp">
<Filter>Scene\Material</Filter>
</ClCompile>
<ClCompile Include="scene\Material\ColorChannel.cpp">
<Filter>Scene\Material</Filter>
</ClCompile>
<ClCompile Include="scene\Material\MaterialQuantizer\ColorQuantizer\ColorBitCutter.cpp">
<Filter>Scene\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClCompile>
<ClCompile Include="core\ColorHelper.cpp">
<Filter>Core\Helpers</Filter>
</ClCompile>
<ClCompile Include="core\StringHelper.cpp">
<Filter>Core\Helpers</Filter>
</ClCompile>
<ClCompile Include="core\CameraPath.cpp">
<Filter>Core</Filter>
</ClCompile>
<ClCompile Include="core\OctreeBuilder\RandomOctreeBuilder.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="core\OctreeBuilder\MaterialLibraryMultiRootOctreeBuilder.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="core\Util\Stopwatch.cpp">
<Filter>Core\Util</Filter>
</ClCompile>
<ClCompile Include="core\Util\BoolArray.cpp">
<Filter>Core\Util</Filter>
</ClCompile>
<ClCompile Include="core\OctreeBuilder\TreeTypeParser.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="core\OctreeBuilder\SettingsParser.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="scene\PoolBuilder\StandardPoolBuilder.cpp">
<Filter>Scene\PoolBuilder</Filter>
</ClCompile>
<ClCompile Include="scene\PoolBuilder\BaseTreePoolBuilder.cpp">
<Filter>Scene\PoolBuilder</Filter>
</ClCompile>
<ClCompile Include="scene\PoolBuilder\AdaptivePointerPoolBuilder.cpp">
<Filter>Scene\PoolBuilder</Filter>
</ClCompile>
<ClCompile Include="scene\PoolBuilder\VirtualNodePoolBuilder.cpp">
<Filter>Scene\PoolBuilder</Filter>
</ClCompile>
<ClCompile Include="core\OctreeBuilder\UniqueIndexShiftColoredOctreeBuilder.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="core\OctreeBuilder\ColorQuantizerFactory.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="inc\pvm\ddsbase.cpp">
<Filter>Scene\PVM</Filter>
</ClCompile>
<ClCompile Include="core\Voxelizer\TriangleMeshVoxelizer.cpp">
<Filter>Core\Voxelizer</Filter>
</ClCompile>
<ClCompile Include="core\Voxelizer\PVMVoxelizer.cpp">
<Filter>Core\Voxelizer</Filter>
</ClCompile>
<ClCompile Include="core\PathHelper.cpp">
<Filter>Core\Helpers</Filter>
</ClCompile>
<ClCompile Include="scene\Octree\HierarchicalShiftingColoredTree.cpp">
<Filter>Scene\Octree</Filter>
</ClCompile>
<ClCompile Include="scene\Octree\HierarchicalColorsOnlyTree.cpp">
<Filter>Scene\Octree</Filter>
</ClCompile>
<ClCompile Include="scene\Octree\BaseTree.cpp">
<Filter>Scene\Octree</Filter>
</ClCompile>
<ClCompile Include="core\OctreeBuilder\BaseOctreeBuilder.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
<ClCompile Include="scene\PointLight.cpp">
<Filter>Scene</Filter>
</ClCompile>
<ClCompile Include="core\LightPath.cpp">
<Filter>Core</Filter>
</ClCompile>
<ClCompile Include="scene\Material\MaterialQuantizer\ColorQuantizer\BaseColorQuantizer.cpp">
<Filter>Scene\Material\MaterialQuantizer\ColorQuantizer</Filter>
</ClCompile>
<ClCompile Include="scene\Material\MaterialQuantizer\NormalQuantizer.cpp">
<Filter>Scene\Material\MaterialQuantizer</Filter>
</ClCompile>
<ClCompile Include="core\OctreeBuilder\NormalQuantizerFactory.cpp">
<Filter>Core\OctreeBuilder</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="shaders\Shader.frag">
<Filter>Shaders</Filter>
</None>
<None Include="shaders\Shader.vert">
<Filter>Shaders</Filter>
</None>
<None Include="shaders\DepthPeel.vert">
<Filter>Shaders</Filter>
</None>
<None Include="shaders\RenderTexture.frag">
<Filter>Shaders</Filter>
</None>
<None Include="shaders\DepthPeel.frag">
<Filter>Shaders</Filter>
</None>
<None Include="shaders\RenderTexture.vert">
<Filter>Shaders</Filter>
</None>
<None Include="shaders\StackRaytrace.frag">
<Filter>Shaders</Filter>
</None>
<None Include="shaders\Raytrace1.frag">
<Filter>Shaders</Filter>
</None>
<None Include="shaders\CombinedStackRaytrace.frag">
<Filter>Shaders</Filter>
</None>
<None Include="shaders\SSAO.frag">
<Filter>Shaders</Filter>
</None>
<None Include="shaders\SSAO2.frag">
<Filter>Shaders</Filter>
</None>
<None Include="shaders\GI.frag">
<Filter>Shaders</Filter>
</None>
<None Include="shaders\SSDS.frag">
<Filter>Shaders</Filter>
</None>
</ItemGroup>
<ItemGroup>
<Text Include="shaders\shader_properties.txt">
<Filter>Shaders</Filter>
</Text>
<Text Include="properties.txt" />
<Text Include="Readme.txt" />
</ItemGroup>
</Project>

330
Research/core/BitHelper.h Normal file
View File

@@ -0,0 +1,330 @@
#pragma once
#include "Defines.h"
#include "CompileTimeArray.h"
#include <vector>
#include <assert.h>
#include "../inc/tbb/parallel_for.h"
template<size_t x> struct BitCount
{
// The line below actually counts the number of bits set in x
enum {
value = (((((x & 0x55) + ((x >> 1) & 0x55)) & 0x33) + ((((x & 0x55) + ((x >> 1) & 0x55)) >> 2) & 0x33)) & 0x0F) +
((((((x & 0x55) + ((x >> 1) & 0x55)) & 0x33) + ((((x & 0x55) + ((x >> 1) & 0x55)) >> 2) & 0x33)) >> 4) & 0x0F)
};
};
typedef generate_array<256, BitCount>::result BitCountLookupTable;
namespace BitHelper
{
inline static unsigned8 GetSet(unsigned64 x)
{
x = (x & 0x5555555555555555) + ((x >> 1) & 0x5555555555555555); // 0x55 = 01010101
x = (x & 0x3333333333333333) + ((x >> 2) & 0x3333333333333333); // 0x33 = 00110011
x = (x & 0x0F0F0F0F0F0F0F0F) + ((x >> 4) & 0x0F0F0F0F0F0F0F0F); // 0x0F = 00001111
x = (x & 0x00FF00FF00FF00FF) + ((x >> 8) & 0x00FF00FF00FF00FF);
x = (x & 0x0000FFFF0000FFFF) + ((x >> 16) & 0x0000FFFF0000FFFF);
x = (x & 0x00000000FFFFFFFF) + ((x >> 32) & 0x00000000FFFFFFFF);
return (unsigned8)x;
}
inline static unsigned8 GetSet(unsigned32 v)
{
// From https://graphics.stanford.edu/~seander/bithacks.html, method only uses 12 operations :)
v = v - ((v >> 1) & 0x55555555); // reuse input as temporary
v = (v & 0x33333333) + ((v >> 2) & 0x33333333); // temp
return (unsigned8)((((v + (v >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24); // count
//x -= ((x >> 1) & 0x55555555);
//x = (((x >> 2) & 0x33333333) + (x & 0x33333333));
//x = (((x >> 4) + x) & 0x0f0f0f0f);
//x += (x >> 8);
//x += (x >> 16);
//return (x & 0x0000003f);
}
inline static unsigned8 GetSet(unsigned16 x)
{
x = (x & 0x5555) + ((x >> 1) & 0x5555); // 0x55 = 01010101
x = (x & 0x3333) + ((x >> 2) & 0x3333); // 0x33 = 00110011
x = (x & 0x0F0F) + ((x >> 4) & 0x0F0F); // 0x0F = 00001111
x = (x & 0x00FF) + ((x >> 8) & 0x00FF);
return (unsigned8)x;
}
inline static unsigned8 GetSet(unsigned8 x)
{
return BitCountLookupTable::data[x];
//// Parallel bit count
//x = (x & 0x55) + ((x >> 1) & 0x55); // 0x55 = 01010101
//x = (x & 0x33) + ((x >> 2) & 0x33); // 0x33 = 00110011
//x = (x & 0x0F) + ((x >> 4) & 0x0F); // 0x0F = 00001111
//return x;
}
template<typename T>
inline T GetLSMaskUntil(const unsigned8 bit) { return (~((T)0)) << bit; }
template<typename T> inline T GetLSSingleBitMask(const unsigned8 bit) { return (T)1 << bit; }
template<typename T, unsigned8 bitsInT = sizeof(T) * 8> inline T GetHSSingleBitMask(const unsigned8 bit) { return (T)1 << (bitsInT - 1 - bit); }
// Template specialization for HSSingleBitMask
template<> inline unsigned8 GetHSSingleBitMask(const unsigned8 pos) { return (unsigned8)0x80 >> pos; }
template<> inline unsigned16 GetHSSingleBitMask(const unsigned8 pos) { return (unsigned16)0x8000 >> pos; }
template<> inline unsigned32 GetHSSingleBitMask(const unsigned8 pos) { return (unsigned32)0x80000000 >> pos; }
template<> inline unsigned64 GetHSSingleBitMask(const unsigned8 pos) { return (unsigned64)0x8000000000000000 >> pos; }
template<typename T, unsigned8 bitsInT = sizeof(T) * 8>
inline T GetLSMask(const unsigned8 startIndex, const unsigned8 endIndex) {
if (startIndex == endIndex) return (T)0;
// Note that s needs to be defined first. If this happens in the same line, I couldn't get the compiler to make sure the size of the datatype is correct
T s = ~((T)0);
unsigned8 firstShift = bitsInT - endIndex;
s <<= firstShift;
s >>= firstShift + startIndex;
s <<= startIndex;
return s;
}
template<typename T, unsigned8 bitsInT = sizeof(T) * 8>
inline T GetHSMask(const unsigned8 startIndex, const unsigned8 endIndex) {
if (startIndex == endIndex) return (T)0;
// Note that s needs to be defined first. If this happens in the same line, I couldn't get the compiler to make sure the size of the datatype is correct
T s = ~((T)0);
unsigned8 firstShift = bitsInT - endIndex;
s >>= firstShift;
s <<= firstShift + startIndex;
s >>= startIndex;
return s;
}
template<typename T, unsigned8 bitsInT = sizeof(T) * 8>
inline unsigned8 GetHSSetBefore(const T value, const unsigned8 pos) { return GetSet((T)(value << (bitsInT - pos))); }
template<typename T> inline bool GetHS(const T value, const unsigned8 pos) { return (GetHSSingleBitMask<T>(pos) & value) != 0; }
template<typename T> inline bool GetLS(const T value, const unsigned8 pos) { return (BitHelper::GetLSSingleBitMask<T>(pos) & value) != 0; }
template<typename T> inline T SetLS(const T value, const T& setMask, const T& setValue) { return (value & ~setMask) | (setMask & setValue); }
template<typename T> inline void SetLS(T& value, const unsigned8 pos) { value |= GetLSSingleBitMask<T>(pos); }
template<typename T> inline void SetHS(T& value, const unsigned8 pos) { value |= GetHSSingleBitMask<T>(pos); }
template<typename T> inline void SetLS(T& value, const unsigned8 pos, const bool& set) {
T bitmask = GetLSSingleBitMask<T>(pos);
value &= ~bitmask; // Clear the bit
if (set) value |= bitmask; // Set it if necessary
}
template<typename T> inline void SetHS(T& value, const unsigned8 pos, const bool& set)
{
T bitmask = GetHSSingleBitMask<T>(pos);
value &= ~bitmask;
if (set) value |= bitmask;
}
inline unsigned32 CeilToNearestPowerOfTwo(unsigned32 v)
{
v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v++;
return v;
}
inline unsigned32 FloorToNearestPowerOfTwo(unsigned32 value) { return CeilToNearestPowerOfTwo(value) >> 1; }
template<typename T>
inline bool IsPowerOfTwo(T v) { return v && !(v & (v - 1)); }
// Log2 = the index of the highest significant bit.
template<typename T>
inline unsigned8 Log2(T v) {
unsigned8 r = 0;
while (v >>= 1) r++;
return (unsigned8)r;
}
template<typename T>
inline unsigned8 Log2Ceil(T v) {
return Log2(v) + (IsPowerOfTwo(v) ? 0 : 1); // If v is not a power of two, the number was rounded down.
}
// 2^x is equal to taking the number 1 and shifting it x indices.
template<typename T>
inline unsigned64 Exp2(const T& v) { return ((unsigned64)1) << v; }
template<typename T>
inline T RoundToBytes(const T& v)
{
if ((v & GetLSMask<T>(0, 3)) != 0) return ((v >> 3) + 1) << 3;
else return v;
}
template<typename T, unsigned8 bitsInT = sizeof(T) * 8>
inline T CircularShiftLeft(T v, T shift) { shift %= bitsInT; return (v << shift) | (v >> (bitsInT - shift)); }
template<typename T, unsigned8 bitsInT = sizeof(T) * 8>
inline T CircularShiftRight(T v, T shift) { shift %= bitsInT; return (v >> shift) | (v << (bitsInT - shift)); }
template<typename T>
inline void SplitInBytesAndMove(T value, std::vector<unsigned8>& destination, size_t offset, size_t size = sizeof(T))
{
SplitInBytesAndMove<T>(value, &destination[0], offset, size);
}
template<typename T>
inline void SplitInBytesAndMove(T value, unsigned8* destination, size_t offset, size_t size = sizeof(T))
{
for (size_t byte = 0; byte < size; byte++)
{
size_t lsByte = size - 1 - byte;
destination[offset + byte] = (unsigned8)((GetLSMask<T>((unsigned8)(lsByte * 8), (unsigned8)((lsByte + 1) * 8)) & value) >> (lsByte << 3));
}
}
template<typename T>
inline std::vector<unsigned8> SplitInBytes(T value, size_t size = sizeof(T))
{
std::vector<unsigned8> res(size);
SplitInBytesAndMove(value, res, 0, size);
return res;
}
template<typename T>
inline void JoinBytes(const std::vector<unsigned8>& source, T& dest, size_t offset = 0, size_t size = sizeof(T)) { JoinBytes(&source[0], dest, offset, size); }
template<typename T>
inline void JoinBytes(const unsigned8* source, T& dest, size_t offset = 0, size_t size = sizeof(T))
{
for (size_t byte = 0; byte < size; byte++)
dest |= source[offset + byte] << ((size - byte - 1) * 8);
}
template<typename T>
inline void JoinBytesLittleEndian(const std::vector<unsigned8>& source, T& dest, size_t offset = 0, size_t size = sizeof(T)) { JoinBytes(&source[0], dest, offset, size); }
template<typename T>
inline void JoinBytesLittleEndian(const unsigned8* source, T& dest, size_t offset = 0, size_t size = sizeof(T))
{
for (size_t byte = 0; byte < size; byte++)
dest |= source[offset + (size - byte - 1)] << ((size - byte - 1) * 8);
}
template<typename T, unsigned8 bitsInT = ((unsigned8)sizeof(T) * 8)>
std::vector<unsigned8> GetBitMapHS(T mask)
{
unsigned setBits = BitHelper::GetSet(mask);
std::vector<unsigned8> bitMap(setBits);
unsigned index = 0;
for (unsigned8 i = 0; i < bitsInT; i++)
{
if (BitHelper::GetHS(mask, i))
bitMap[index++] = i;
}
return bitMap;
}
// Packs the value v tightly, meaning that only the bits that are set in the mask will be kept, and they will be shifted so that they are next to each other
template<typename T, unsigned8 bitsInType = sizeof(T) * 8>
inline T PackTight(const T& v, const T& mask)
{
unsigned8 bitOffset = bitsInType - GetSet(mask);
T res = 0;
for (T i = 0; i < bitsInType; i++)
{
T curBitMask = GetHSSingleBitMask(i);
if ((mask & curBitMask) != 0)
{
if ((v & curBitMask) != 0) SetHS(res, bitOffset);
bitOffset++;
}
}
return res;
}
template<typename T, unsigned8 bitsInType = sizeof(T) * 8>
inline T UnpackTight(const T& v, const T& mask)
{
unsigned8 bitOffset = bitsInType - GetSet(mask);
T res = 0;
for (unsigned8 i = 0; i < bitsInType; i++)
if (GetHS(mask, i))
if (GetHS(v, bitOffset++)) SetHS(res, i);
return res;
}
// Used to tightly pack a whole vector of values at once. Offset should give the offset in bits within the first packed value
template<typename T_packed, typename T_unpacked, unsigned8 bitsInPacked = sizeof(T_packed) * 8, unsigned8 bitsInUnpacked = sizeof(T_unpacked) * 8>
std::vector<T_packed> PackTight(const std::vector<T_unpacked>& input, const std::vector<unsigned8>& bitMap, const unsigned8 offset = 0, const size_t startIndex = 0, size_t endIndex = ~size_t(0))
{
assert(offset < bitsInPacked);
if (endIndex > input.size()) endIndex = input.size();
size_t setBits = bitMap.size();
size_t requiredBits = setBits * (endIndex - startIndex) + offset;
size_t outputSize = requiredBits / bitsInPacked + (((requiredBits % bitsInPacked) == 0) ? 0 : 1);
std::vector<T_packed> packed(outputSize);
// Compress the new data (in parallel per packed byte)
tbb::parallel_for(size_t(0), outputSize, [&](size_t i)
{
size_t startBit = i * bitsInPacked;
T_packed cur = 0;
for (size_t j = 0; j < bitsInPacked; j++)
{
size_t bit = startBit + j;
if (bit < offset) continue;
bit -= offset;
size_t sourceIndex = bit / setBits;
size_t sourceBitIndex = bit % setBits;
size_t inputIndex = startIndex + sourceIndex;
if (inputIndex >= endIndex) break;
auto source = input[inputIndex];
if (GetHS(source, bitMap[sourceBitIndex]))
SetHS(cur, (unsigned8)j);
}
packed[i] = cur;
});
return packed;
}
// Used to tightly pack a whole vector of values at once. Offset should give the offset in bits within the first packed value
template<typename T_packed, typename T_unpacked, unsigned8 bitsInPacked = sizeof(T_packed) * 8, unsigned8 bitsInUnpacked = sizeof(T_unpacked) * 8>
std::vector<T_packed> PackTight(const std::vector<T_unpacked>& input, const T_unpacked& mask, const unsigned8 offset = 0, const size_t startIndex = 0, size_t endIndex = ~size_t(0))
{
return PackTight<T_packed, T_unpacked, bitsInPacked, bitsInUnpacked>(input, GetBitMapHS(mask), offset, startIndex, endIndex);
}
// Unpack a single packed byte at some location.
// packed should contain the vector with packed data
// i gives the index of the value to unpack (unpacked value index)
// bitMap should contain the bitMap for the mask to be used (GetBitMapHS(mask))
// offset gives the offset from which the data starts
// packedArrayOffset gives the index where the packed data with the current mask starts
template<typename T_packed, typename T_unpacked, unsigned8 bitsInPacked = sizeof(T_packed) * 8, unsigned8 bitsInUnpacked = sizeof(T_unpacked) * 8>
T_unpacked UnpackTightAt(const std::vector<T_packed>& packed, const size_t& i, const std::vector<unsigned8>& bitMap, const unsigned8& offset = 0, const size_t& packedArrayOffset = 0)
{
assert(offset < bitsInPacked);
size_t setBits = bitMap.size();
size_t divisionShift = (bitsInPacked >> 3) * 3; // (bitsInPacked / 8) * 3
size_t modulusMask = BitHelper::GetLSMask<size_t>(0, (unsigned8)divisionShift); // Mask that captures the bits that are shifted out by the divisionShift
T_unpacked value = 0;
for (size_t j = 0; j < bitMap.size(); j++)
{
size_t bit = i * setBits + j + offset;
size_t byteIndex = bit >> divisionShift; // Divide by the number of bits in the packed type (gives the index of the packed value to look at)
T_packed bitInByte = (T_packed)(bit & modulusMask); // Modulus by the number of bits in the packed type (gives the bit index within the packed type)
if (BitHelper::GetHS(packed[packedArrayOffset + byteIndex], bitInByte)) // If the bit in the packed type is set, it should also be in the unpacked type
SetHS(value, bitMap[j]);
}
return value;
}
template<typename T_packed, typename T_unpacked, unsigned8 bitsInPacked = sizeof(T_packed) * 8, unsigned8 bitsInUnpacked = sizeof(T_unpacked) * 8>
T_unpacked UnpackTightAt(const std::vector<T_packed>& packed, const size_t& i, const T_unpacked mask, const unsigned8& offset = 0, const size_t& packedArrayOffset = 0)
{
return UnpackTightAt<T_packed, T_unpacked, bitsInPacked, bitsInUnpacked>(packed, i, GetBitMapHS(mask), offset, packedArrayOffset);
}
};

201
Research/core/Camera.cpp Normal file
View File

@@ -0,0 +1,201 @@
#include "Defines.h"
#include "Camera.h"
#include <stdio.h>
Camera* Camera::mInstance = NULL;
void Camera::Create() {
if (mInstance == NULL)
mInstance = new Camera();
}
void Camera::Destroy() {
if (mInstance != NULL)
delete mInstance;
mInstance = NULL;
}
Camera* Camera::Instance() {
return mInstance;
}
//************************************
// Update camera position and orientation for both camera modes based on change in mouse position
//************************************
void Camera::UpdateMouse(glm::vec2 mouseChange, float dTime) {
if (mFreeCam) {
mHorizontalRotation += mRotationSpeed * mouseChange.x;
mVerticalRotation += mRotationSpeed * mouseChange.y;
mVerticalRotation = glm::min(mVerticalRotation, mPi2 - .1f);
mVerticalRotation = glm::max(mVerticalRotation, -mPi2 + .1f);
}
else {
mAzimuth += mSurfingSpeed * mouseChange.x;
mAltitude -= mSurfingSpeed * mouseChange.y;
mAltitude = glm::min(mAltitude, mPi2 - .1f);
mAltitude = glm::max(mAltitude, -mPi2 + .1f);
}
Compute();
}
//************************************
// Update camera position for free camera mode based on key presses
//************************************
void Camera::UpdateKeys(glm::vec3 movement, float dTime) {
if (mFreeCam)
mPosition += mMovingSpeed * dTime * (movement.x * mDirection + movement.y * mRight + movement.z * mUp);
else
mPivot += mMovingSpeed * dTime * glm::vec3(movement.x, movement.z, movement.y);
}
//************************************
// Update camera zoom or field of view for both camera modes based on change in scroll
//************************************
void Camera::UpdateScroll(glm::vec2 offset, float dTime) {
// Change FOV in free camera mode
if (mFreeCam) {
mFOV -= mZoomSpeed * offset.y;
mFOV = glm::clamp(mFOV, .1f, mPi2);
}
else {
mPosition -= mPosition * mZoomSpeed * offset.y;
}
}
void Camera::ToggleMode() {
mFreeCam = !mFreeCam;
float r = glm::length(mPosition);
if (mFreeCam) {
mVerticalRotation = glm::asin(-mPosition.y / r);
mHorizontalRotation = glm::atan(-mPosition.x, -mPosition.z);
}
//else {
// mAltitude = glm::asin(mPosition.y / r);
// mAzimuth = glm::atan(mPosition.x, mPosition.z);
//}
Compute();
//////Reset();
}
bool Camera::IsFree()
{
return mFreeCam;
}
//************************************
// Compute camera orientation from rotations for free camera mode or camera position from trackball camera mode
//************************************
void Camera::Compute() {
if (mFreeCam) {
mDirection = glm::vec3(
cos(mVerticalRotation) * sin(mHorizontalRotation),
sin(mVerticalRotation),
cos(mVerticalRotation) * cos(mHorizontalRotation)
);
mRight = glm::vec3(
sin(mHorizontalRotation - 1.57f),
0,
cos(mHorizontalRotation - 1.57f)
);
mUp = glm::cross(mRight, mDirection);
}
else {
double r = glm::length(mPosition - mPivot);
double x = r * cos(mAltitude) * sin(mAzimuth);
double y = r * sin(mAltitude);
double z = r * cos(mAltitude) * cos(mAzimuth);
mPosition = mPivot + glm::vec3(x, y, z);
mDirection = glm::normalize(mPivot - mPosition);
}
}
void Camera::Reset() {
mFOV = 1.f;//QT
mPosition = glm::vec3(785.f, 544.f, -847.f);//QT
mHorizontalRotation = 0.f;//QT
mVerticalRotation = 0.f;//QT
mAltitude = .44f;//QT
mAzimuth = 2.39f;//QT
mPivot = glm::vec3(0);//QT
Compute();
}
glm::vec3 Camera::GetPosition() const {
return mPosition;
}
void Camera::SetPosition(glm::vec3 position)
{
mPosition = position;
}
glm::vec3 Camera::GetDirection() const {
return mDirection;
}
void Camera::SetDirection(glm::vec3 direction)
{
mDirection = glm::normalize(direction);
}
glm::vec3 Camera::GetTarget() const {
if (mFreeCam)
return mPosition + mDirection;
else
return mPivot;
}
void Camera::SetTarget(glm::vec3 target)
{
if (mFreeCam)
{
mDirection = glm::normalize(target - mPosition);
} else
mPivot = mPosition;
}
glm::vec3 Camera::GetPivot() const { return mPivot; }
void Camera::SetPivot(glm::vec3 pivot) { mPivot = pivot; }
double Camera::GetAltitude() const { return mAltitude; }
void Camera::SetAltitude(double altitude) { mAltitude = altitude; }
float Camera::GetFOV() const { return mFOV; }
void Camera::SetFOV(float fov) { mFOV = fov; }
float Camera::GetNear() const { return mNear; }
void Camera::SetNear(float near) { mNear = near; }
float Camera::GetFar() const { return mFar; }
void Camera::SetFar(float far) { mFar = far; }
void Camera::SetMovingSpeed(float speed) { mMovingSpeed = speed; }
float Camera::GetMovingSpeed() { return mMovingSpeed; }
void Camera::SetRotationSpeed(float speed) { mRotationSpeed = speed; }
float Camera::GetRotationSpeed() { return mRotationSpeed; }
Camera::Camera() {
mNear = 1.f;//QT
mFar = 500000.f;//QT
mMovingSpeed = 200.f;//QT
mRotationSpeed = 0.005f;//QT
mSurfingSpeed = 0.01f;//QT
mZoomSpeed = 0.1f;//QT
mFreeCam = false;//QT
Reset();
}
Camera::~Camera() {
}

71
Research/core/Camera.h Normal file
View File

@@ -0,0 +1,71 @@
#pragma once
#include "../inc/glm/glm.hpp"
class Camera {
public:
static void Create();
static void Destroy();
static Camera* Instance();
void UpdateMouse(glm::vec2 mouseChange, float dTime);
void UpdateKeys(glm::vec3 movement, float dTime);
void UpdateScroll(glm::vec2 offset, float dTime);
void ToggleMode();
bool IsFree();
void Compute();
void Reset();
glm::vec3 GetPosition() const;
void SetPosition(glm::vec3 position);
glm::vec3 GetDirection() const;
void SetDirection(glm::vec3 direction);
glm::vec3 GetTarget() const;
void SetTarget(glm::vec3 target);
glm::vec3 GetPivot() const;
void SetPivot(glm::vec3 pivot);
double GetAltitude() const;
void SetAltitude(double altitude);
float GetFOV() const;
void SetFOV(float fov);
float GetNear() const;
void SetNear(float near);
float GetFar() const ;
void SetFar(float far);
void SetMovingSpeed(float speed);
float GetMovingSpeed();
void SetRotationSpeed(float speed);
float GetRotationSpeed();
protected:
private:
Camera();
~Camera();
static Camera* mInstance;
bool mFreeCam; // camera mode; free-moving mode or trackball
glm::vec3 mPosition;
glm::vec3 mDirection; // direction, negative z-axis, used for free camera mode
glm::vec3 mRight; // right vector, x-axis, used for free camera mode
glm::vec3 mUp; // up vector, y-axis, used for free camera mode
float mHorizontalRotation; // rotation around y-axis, used for free camera mode
float mVerticalRotation; // rotation around x-axis, used for free camera mode
float mAltitude; // camera altitude/elevation, used for trackball camera mode
float mAzimuth; // camera azimuth, used for trackball camera mode
glm::vec3 mPivot; // pivot point, used for trackball camera mode
float mFOV; // field of view in y-direction
float mNear;
float mFar;
float mMovingSpeed; // free camera moving speed
float mRotationSpeed; // free camera rotation speed
float mSurfingSpeed; // trackball camera surfing speed
float mZoomSpeed; // scrolling speed/sensitivity, used for zooming
};

View File

@@ -0,0 +1,16 @@
#include "CameraPath.h"
#include "MathHelper.h"
#include "../inc/glm/glm.hpp"
CameraState CameraStateInterpolator::operator()(const CameraState& before, const CameraState& after, const double& time)
{
float t = (float)time;
CameraState res;
res.position = MathHelper::lerp(t, before.position, after.position);
res.direction = MathHelper::slerp(t, before.direction, after.direction);
res.target = MathHelper::lerp(t, before.target, after.target);
res.FOV = MathHelper::lerp(t, before.FOV, after.FOV);
res.nearPlane = MathHelper::lerp(t, before.nearPlane, after.nearPlane);
res.farPlane = MathHelper::lerp(t, before.farPlane, after.farPlane);
return res;
};

View File

@@ -0,0 +1,21 @@
#pragma once
#include <string>
#include <vector>
#include "../inc/glm/common.hpp"
#include "Util/Path.h"
struct CameraState
{
glm::vec3 position;
glm::vec3 direction;
glm::vec3 target;
float FOV;
float nearPlane;
float farPlane;
};
struct CameraStateInterpolator {
CameraState operator()(const CameraState& before, const CameraState& after, const double& time);
};
typedef Path<CameraState, CameraStateInterpolator> CameraPath;

View File

@@ -0,0 +1,175 @@
#pragma once
#include "Defines.h"
#include <unordered_map>
#include <vector>
#include "../inc/tbb/parallel_sort.h"
#include "../inc/tbb/parallel_reduce.h"
#include "../inc/tbb/blocked_range.h"
#include "../inc/glm/glm.hpp"
#include <stdio.h>
#include <iostream>
#include <numeric>
class CollectionHelper
{
public:
// Modifies the sequence so that it only contains unique elements. To do this quickly, the elements will be sorted first, meaning the original order is lost.
template<typename T, typename Compare = std::less<T>>
inline static void Unique(std::vector<T>& data, Compare comparer = Compare())
{
tbb::parallel_sort(data.begin(), data.end(), comparer);
data.erase(std::unique(data.begin(), data.end()), data.end());
data.shrink_to_fit();
}
// Modifies the sequence so that it only contains unique elements. To do this quickly, the elements will be sorted first, meaning the original order is lost.
template<typename T, typename Compare = std::less<T>>
inline static void UniqueSerial(std::vector<T>& data, Compare comparer = Compare())
{
std::sort(data.begin(), data.end(), comparer);
data.erase(std::unique(data.begin(), data.end()), data.end());
data.shrink_to_fit();
}
template<typename T, typename Compare = std::less<T>>
inline static size_t CountUnique(const std::vector<T>& data, Compare comparer = Compare())
{
// Copy the data
std::vector<T> copy(data.size());
std::copy(data.begin(), data.end(), copy.begin());
Unique(copy, comparer);
return copy.size();
}
// Walks through the given data vector and checks if it contains a certain value. O(n) performance.
template<typename T>
inline static bool Contains(const std::vector<T>& data, const T& value)
{
bool contains = false;
for (auto mat : data)
{
if (mat == value)
{
contains = true;
break;
}
}
return contains;
}
template<typename T, typename Compare = std::less<T>>
inline static size_t MinIndex(const std::vector<T>& data, Compare comparer = Compare())
{
// Finds the minimum value according to some comparer
return tbb::parallel_reduce(tbb::blocked_range<size_t>(0, data.size()), size_t(0),
[&](const tbb::blocked_range<size_t>& r, size_t init)
{
for (size_t i = r.begin(); i != r.end(); i++)
if (comparer(data[i], data[init]))
init = i;
return init;
},
[&](size_t value1, size_t value2)
{
if (comparer(data[value1], data[value2]))
return value1;
else
return value2;
});
}
template<typename T>
inline static std::unordered_map<T, size_t> GetIndexMap(const std::vector<T>& data)
{
std::unordered_map<T, size_t> res;
for (size_t i = 0; i < data.size(); i++)
res.insert(std::pair<T, size_t>(data[i], i));
return res;
}
template<typename T>
inline static void PrintContents(const std::vector<T>& data, size_t count = 0)
{
if (count == 0) count = data.size();
for (size_t i = 0; i < count; i++)
{
std::cout << std::to_string(data[i]).c_str();
if (i < count - 1)
std::cout << ", ";
else
std::cout << "\n";
}
}
template <typename T>
inline static T Sum(const std::vector<T>& data)
{
return std::accumulate(data.begin(), data.end(), (T)0);
}
// Calculates the max given some comparer. Comparer should be a functor that returns true if the first value passed is the biggest value.
template<typename T, typename Comparer = std::greater<T>>
inline static T Max(const std::vector<T>& data, Comparer comp = std::greater<T>())
{
if (data.empty()) return T();
T max = data[0];
for (const T& value : data)
if (comp(value, max)) max = value;
return max;
}
template <typename T>
inline static double CalculateMean(const std::vector<T>& data)
{
return ((double)Sum(data)) / ((double)data.size());
}
template <typename T>
inline static double CalculateVariance(const std::vector<T>& data, double mean)
{
double variance = 0;
for (T v : data)
{
double meanDiff = ((double)v) - mean;
variance += meanDiff * meanDiff;
}
variance /= (double)data.size();
return variance;
}
template <typename T>
inline static double CalculateVariance(const std::vector<T>& data)
{
return CalculateVariance(data, CalculateMean(data));
}
template <typename T>
inline static T CalculateMedian(const std::vector<T>& data)
{
std::vector<T> dataCopy(data.size());
std::copy(data.begin(), data.end(), dataCopy.begin());
tbb::parallel_sort(dataCopy.begin(), dataCopy.end());
return dataCopy[dataCopy.size() / 2];
}
template <typename T>
inline static size_t Count(const std::vector<T>& data, const T& value)
{
size_t count = 0;
for (T v : data) if (v == value) count++;
return count;
}
template <typename T>
inline static void PrintStats(const std::vector<T>& data)
{
double mean = CalculateMean(data);
unsigned32 zeroCount = (unsigned32)Count(data, 0);
double variance = CalculateVariance(data);
T median = CalculateMedian(data);
printf("Size: %llu, Zero count: %u, Mean: %f, Median: %i, Variance: %f\n", data.size(), zeroCount, mean, median, variance);
}
};

View File

@@ -0,0 +1,244 @@
#include "ColorHelper.h"
#include <algorithm>
// Conversion matrix from RGB to XYZ (assuming sRGB values in 0-1 range, with D65 as reference white
// http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
const glm::mat3 ColorHelper::matRGBtoXYZ = glm::transpose(glm::mat3(
0.4124564, 0.3575761, 0.1804375,
0.2126729, 0.7151522, 0.0721750,
0.0193339, 0.1191920, 0.9503041
));
// Conversion matrix from XYZ to sRGB (assuming D65 is used as reference white)
// http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
const glm::mat3 ColorHelper::matXYZtoRGB = glm::transpose(glm::mat3(
3.2404542, -1.5371385, -0.4985314,
-0.9692660, 1.8760108, 0.0415560,
0.0556434, -0.2040259, 1.0572252
));
const glm::vec3 ColorHelper::D65WhitePoint = glm::vec3(0.95047, 1.00, 1.08883);
const glm::vec3 ColorHelper::invD65WhitePoint = 1.f / ColorHelper::D65WhitePoint;
const float ColorHelper::inv255 = 1.f / 255.f;
const float ColorHelper::tLimit = 0.008856f;
const float ColorHelper::tInvLimit = 6.f / 29.f;
const float ColorHelper::epsilon = 0.008856f;
const float ColorHelper::kappa = 903.3f;
// K-values for Delta-E calculation
const float ColorHelper::kl = 1;
const float ColorHelper::kc = 1;
const float ColorHelper::kh = 1;
const float ColorHelper::K1 = 0.045f;
const float ColorHelper::K2 = 0.015f;
// Based on:
// http://en.wikipedia.org/wiki/Lab_color_space
glm::vec3 ColorHelper::RGBtoLAB(glm::u8vec3 rgb)
{
glm::vec3 xyz = RGBtoXYZ(rgb);
return XYZtoLAB(xyz);
}
glm::u8vec3 ColorHelper::LABtoRGB(glm::vec3 lab)
{
glm::vec3 xyz = LABtoXYZ(lab);
return XYZtoRGB(xyz);
}
glm::vec3 ColorHelper::XYZtoLAB(glm::vec3 xyz)
{
glm::vec3 n = xyz * invD65WhitePoint;
float fx = f(n.x);
float fy = f(n.y);
float fz = f(n.z);
return glm::vec3(
116.f * fy - 16.f,
500.f * (fx - fy),
200.f * (fy - fz)
);
}
float ColorHelper::f(float t)
{
if (t > epsilon)
// t ^ (1 / 3)
return std::pow(t, 0.3333333333f);
else
//(1 / 3) * (29 / 6) ^ 2 * t + (4 / 29)
return (kappa * t + 16.f) / 116.f;
}
glm::vec3 ColorHelper::LABtoXYZ(glm::vec3 lab)
{
float fy = (lab.x + 16.f) / 116.f;
float fx = lab.y * 0.002f + fy;
float fz = fy - 0.005f * lab.z;
float xr = fx * fx * fx;
if (xr <= epsilon) xr = (116.f * fx - 16.f) / kappa;
float yr = 0;
if (lab.x > kappa * epsilon)
yr = std::pow((lab.x + 16.f) / 116.f, 3.f);
else
yr = lab.x / kappa;
float zr = fz * fz * fz;
if (zr <= epsilon) zr = (116.f * fz - 16.f) / kappa;
return glm::vec3(xr, yr, zr) * D65WhitePoint;
}
float ColorHelper::fInv(float t)
{
if (t > tInvLimit)
// t ^ 3
return std::pow(t, 3.f);
else
// 3 * (6 / 29) ^ 2 * (t - (4 / 29))
return 0.12841854934f * (t - 0.13793103448f);
}
glm::vec3 ColorHelper::RGBtoXYZ(glm::u8vec3 rgb)
{
glm::vec3 lrgb(toLinearRGB(rgb.x), toLinearRGB(rgb.y), toLinearRGB(rgb.z));
return matRGBtoXYZ * lrgb;
}
glm::u8vec3 ColorHelper::XYZtoRGB(glm::vec3 xyz)
{
glm::vec3 lrgb = matXYZtoRGB * xyz;
return glm::u8vec3(fromLinearRGB(lrgb.x), fromLinearRGB(lrgb.y), fromLinearRGB(lrgb.z));
}
glm::u8vec3 ColorHelper::RGBtoHSV(glm::u8vec3 rgb)
{
glm::u8vec3 hsv;
unsigned char rgbMin, rgbMax;
rgbMin = rgb.r < rgb.g ? (rgb.r < rgb.b ? rgb.r : rgb.b) : (rgb.g < rgb.b ? rgb.g : rgb.b);
rgbMax = rgb.r > rgb.g ? (rgb.r > rgb.b ? rgb.r : rgb.b) : (rgb.g > rgb.b ? rgb.g : rgb.b);
hsv.z = rgbMax;
if (hsv.z == 0)
{
hsv.x = 0;
hsv.y = 0;
return hsv;
}
hsv.y = 255 * long(rgbMax - rgbMin) / hsv.z;
if (hsv.y == 0)
{
hsv.x = 0;
return hsv;
}
if (rgbMax == rgb.r)
hsv.x = 0 + 43 * (rgb.g - rgb.b) / (rgbMax - rgbMin);
else if (rgbMax == rgb.g)
hsv.x = 85 + 43 * (rgb.b - rgb.r) / (rgbMax - rgbMin);
else
hsv.x = 171 + 43 * (rgb.r - rgb.g) / (rgbMax - rgbMin);
return hsv;
}
glm::u8vec3 ColorHelper::HSVtoRGB(glm::u8vec3 hsv)
{
glm::u8vec3 rgb;
unsigned char region, remainder, p, q, t;
if (hsv.y == 0)
{
rgb.r = hsv.z;
rgb.g = hsv.z;
rgb.b = hsv.z;
return rgb;
}
region = hsv.x / 43;
remainder = (hsv.x - (region * 43)) * 6;
p = (hsv.z * (255 - hsv.y)) >> 8;
q = (hsv.z * (255 - ((hsv.y * remainder) >> 8))) >> 8;
t = (hsv.z * (255 - ((hsv.y * (255 - remainder)) >> 8))) >> 8;
switch (region)
{
case 0:
rgb.r = hsv.z; rgb.g = t; rgb.b = p;
break;
case 1:
rgb.r = q; rgb.g = hsv.z; rgb.b = p;
break;
case 2:
rgb.r = p; rgb.g = hsv.z; rgb.b = t;
break;
case 3:
rgb.r = p; rgb.g = q; rgb.b = hsv.z;
break;
case 4:
rgb.r = t; rgb.g = p; rgb.b = hsv.z;
break;
default:
rgb.r = hsv.z; rgb.g = p; rgb.b = q;
break;
}
return rgb;
}
float ColorHelper::toLinearRGB(unsigned8 c)
{
float cf = float(c) * inv255;
if (cf <= 0.04045f)
return cf / 12.92f;
else
return std::pow((cf + 0.055f) / 1.055f, 2.4f);
}
unsigned8 ColorHelper::fromLinearRGB(float c)
{
if (c <= 0.0031308f)
return (unsigned8)std::round(12.92f * c * 255.f);
else
// ((1 + 0.055) * c) ^ (1 / 2.4) - 0.055
return (unsigned8)std::round((1.055 * std::pow(c, 1.f / 2.4f) - 0.055) * 255.f);
}
float ColorHelper::GetDeltaEFromLAB(glm::vec3 lab1, glm::vec3 lab2)
{
// Implementation based on: http://en.wikipedia.org/wiki/Color_difference
// Calculation
float deltaL = lab1.x - lab2.x;
float C1 = std::sqrt(lab1.y * lab1.y + lab1.z * lab1.z);
float C2 = std::sqrt(lab2.y * lab2.y + lab2.z * lab2.z);
float deltaC = C1 - C2;
float deltaA = lab1.y - lab2.y;
float deltaB = lab1.z - lab2.z;
float deltaH = std::sqrt(deltaA * deltaA + deltaB * deltaB - deltaC * deltaC);
float SL = 1.f;
float SC = 1.f + K1 * C1;
float SH = 1.f + K2 * C1;
// Delta E = \sqrt{ \left(\frac{ \Delta L^* }{k_L S_L}\right) ^ 2 + \left(\frac{ \Delta C^*_{ ab } }{k_C S_C}\right) ^ 2 + \left(\frac{ \Delta H^*_{ ab } }{k_H S_H}\right) ^ 2 }
float term1 = deltaL / (kl * SL);
float term2 = deltaC / (kc * SC);
float term3 = deltaH / (kh * SH);
return std::sqrt(term1 * term1 + term2 * term2 + term3 * term3);
}
float ColorHelper::GetDeltaEFromXYZ(glm::vec3 xyz1, glm::vec3 xyz2)
{
return GetDeltaEFromLAB(XYZtoLAB(xyz1), XYZtoLAB(xyz2));
}
float ColorHelper::GetDeltaEFromRGB(glm::u8vec3 rgb1, glm::u8vec3 rgb2)
{
return GetDeltaEFromLAB(RGBtoLAB(rgb1), RGBtoLAB(rgb2));
}

View File

@@ -0,0 +1,49 @@
#pragma once
#include "../inc/glm/glm.hpp"
#include "Defines.h"
class ColorHelper
{
public:
static glm::vec3 RGBtoLAB(glm::u8vec3 rgb);
static glm::u8vec3 LABtoRGB(glm::vec3 lab);
static glm::vec3 XYZtoLAB(glm::vec3 xyz);
static glm::vec3 LABtoXYZ(glm::vec3 lab);
static glm::vec3 RGBtoXYZ(glm::u8vec3 rgb);
static glm::u8vec3 XYZtoRGB(glm::vec3 xyz);
static glm::u8vec3 RGBtoHSV(glm::u8vec3 rgb);
static glm::u8vec3 HSVtoRGB(glm::u8vec3 hsv);
// Use the CIE94 standard for calculating the visual difference between two colors in CIELAB space (Delta E)
static float GetDeltaEFromLAB(glm::vec3 lab1, glm::vec3 lab2);
// Use the CIE94 standard for calculating the visual difference between two colors in CIE XYZ space (Delta E)
static float GetDeltaEFromXYZ(glm::vec3 xyz1, glm::vec3 xyz2);
// Use the CIE94 standard for calculating the visual difference between two colors in RGB (Delta E)
static float GetDeltaEFromRGB(glm::u8vec3 rgb1, glm::u8vec3 rgb2);
private:
static const glm::mat3 matRGBtoXYZ;
static const glm::mat3 matXYZtoRGB;
static const float inv255;
static const glm::vec3 D65WhitePoint;
static const glm::vec3 invD65WhitePoint;
static const float epsilon;
static const float kappa;
// k_L, k_C and k_H are usually 1. For the textile industry k_L = 2
static const float kl;
static const float kc;
static const float kh;
// K_1 and K_2 are standard values. These are for the graphical arts industry.
static const float K1;
static const float K2;
static float toLinearRGB(unsigned8 c);
static unsigned8 fromLinearRGB(float c);
static float f(float t);
static float fInv(float t);
static const float tLimit;
static const float tInvLimit;
};

29
Research/core/Comparers.h Normal file
View File

@@ -0,0 +1,29 @@
#pragma once
#include <unordered_map>
#include "Defines.h"
#include "../inc/glm/common.hpp"
struct u8vec3comparer {
bool operator()(const glm::u8vec3& color1, const glm::u8vec3& color2) const
{
if (color1.r != color2.r)
return color1.r < color2.r;
else if (color1.g != color2.g)
return color1.g < color2.g;
else if (color1.b != color2.b)
return color1.b < color2.b;
else
return false;
}
};
template<typename T>
struct HashComparer
{
bool operator()(const T& x, const T& y) const
{
std::hash<T> hasher;
return hasher.operator()(x) < hasher.operator()(y);
}
};

View File

@@ -0,0 +1,19 @@
#pragma once
#include<sstream>
#ifdef __MINGW32__
namespace std {
template<typename T>
std::string to_string(T value) {
//create an output string stream
std::ostringstream os;
//throw the value into the string stream
os << value;
//convert the string stream into a string and return
return os.str();
}
}
#endif

View File

@@ -0,0 +1,24 @@
#pragma once
// These templates make sure that arrays can be generated at compile time. Ideal for lookup tables!
template<unsigned... args> struct ArrayHolder {
static const unsigned data[sizeof...(args)];
};
template<unsigned... args>
const unsigned ArrayHolder<args...>::data[sizeof...(args)] = { args... };
template<size_t N, template<size_t> class F, unsigned... args>
struct generate_array_impl {
typedef typename generate_array_impl<N - 1, F, F<N>::value, args...>::result result;
};
template<template<size_t> class F, unsigned... args>
struct generate_array_impl<0, F, args...> {
typedef ArrayHolder<F<0>::value, args...> result;
};
template<size_t N, template<size_t> class F>
struct generate_array {
typedef typename generate_array_impl<N - 1, F>::result result;
};

212
Research/core/Controls.cpp Normal file
View File

@@ -0,0 +1,212 @@
#include "../inc/gl/glfw3.h"
#include "../inc/glm/glm.hpp"
#include "../Renderer.h"
#include "Defines.h"
#include "Camera.h"
#include "Controls.h"
Controls* Controls::mInstance = NULL;
const float Controls::RUNNINGSPEEDRATIO = 2.f;
const float Controls::CRAWLSPEEDRATIO = 0.5f;
const float Controls::SPEEDINCREASERATIO = 1.25f;
void Controls::Create(GLFWwindow* window, bool fullscreen) {
if (mInstance == NULL)
mInstance = new Controls(window, fullscreen);
}
void Controls::Destroy() {
if (mInstance != NULL)
delete mInstance;
mInstance = NULL;
}
Controls* Controls::Instance() {
return mInstance;
}
void Controls::Run() {
if (mLastTime == 0)
mLastTime = float(glfwGetTime());
mCurrentTime = float(glfwGetTime());
mDeltaTime = mCurrentTime - mLastTime;
mLastTime = mCurrentTime;
mOldMouseX = mMouseX;
mOldMouseY = mMouseY;
glfwGetCursorPos(mWindow, &mMouseX, &mMouseY);
ListenToMouse();
ListenToKeys();
}
void Controls::ListenToMouse() {
if (!mDragMouse || glfwGetMouseButton(mWindow, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS)
mCamera->UpdateMouse(glm::vec2(mOldMouseX - mMouseX, mOldMouseY - mMouseY), mDeltaTime);
}
void Controls::ListenToKeys() {
if (CheckKey(GLFW_KEY_ESCAPE))//QT
mState = State::EXIT;
if (CheckKey(GLFW_KEY_SPACE, true))//QT
mState = mState == State::PAUSED ? State::RUNNING : State::PAUSED;
glm::vec3 movement(0);
movement.x += CheckKey(GLFW_KEY_UP) || CheckKey(GLFW_KEY_W);//QT
movement.x -= CheckKey(GLFW_KEY_DOWN) || CheckKey(GLFW_KEY_S);
movement.y += CheckKey(GLFW_KEY_RIGHT) || CheckKey(GLFW_KEY_D);
movement.y -= CheckKey(GLFW_KEY_LEFT) || CheckKey(GLFW_KEY_A);
movement.z += CheckKey(GLFW_KEY_Q);
movement.z -= CheckKey(GLFW_KEY_E);
if (CheckKey(GLFW_KEY_LEFT_SHIFT))
movement *= RUNNINGSPEEDRATIO;
if (CheckKey(GLFW_KEY_LEFT_CONTROL))
movement *= CRAWLSPEEDRATIO;
if (CheckKey(GLFW_KEY_MINUS, true))
{
mCamera->SetMovingSpeed(mCamera->GetMovingSpeed() * (1.f / SPEEDINCREASERATIO));
//mCamera->SetRotationSpeed(mCamera->GetRotationSpeed() * (1.f / SPEEDINCREASERATIO));
}
if (CheckKey(GLFW_KEY_EQUAL, true))
{
mCamera->SetMovingSpeed(mCamera->GetMovingSpeed() * SPEEDINCREASERATIO);
//mCamera->SetRotationSpeed(mCamera->GetRotationSpeed() * SPEEDINCREASERATIO);
}
mCamera->UpdateKeys(movement, mDeltaTime);
if (CheckKey(GLFW_KEY_C, true)) // C: Toggle camera mode
mCamera->ToggleMode();
if (CheckKey(GLFW_KEY_X, true)) // X: Reset the camera to original position
mCamera->Reset();
if (CheckKey(GLFW_KEY_L, true)) // L: Update light direction
Renderer::Instance()->UpdateLightDirection();
if (CheckKey(GLFW_KEY_K, true)) // K: Turn on/off light
Renderer::Instance()->ToggleLight();
if (CheckKey(GLFW_KEY_J, true)) // J: Toggle AO mode
Renderer::Instance()->ToggleAOMode();
if (CheckKey(GLFW_KEY_H, true)) // H: Toggle reflections
Renderer::Instance()->ToggleReflections();
if (CheckKey(GLFW_KEY_R, true)) // R: Reload the shaders
Renderer::Instance()->ReloadShaders();
if (CheckKey(GLFW_KEY_F, true)) // F: Toggles fullscreen
{
mFullScreen = !mFullScreen;
Renderer::Instance()->ToggleFullscreen(mFullScreen);
return;
}
if (CheckKey(GLFW_KEY_LEFT_BRACKET, true)) // [: Decreases the octree rendering depth (for improved performance and debugging)
Renderer::Instance()->DecreaseOctreeRenderLevel();
if (CheckKey(GLFW_KEY_RIGHT_BRACKET, true)) // ]: Increases the octree render depth
Renderer::Instance()->IncreaseOctreeRenderLevel();
if (CheckKey(GLFW_KEY_P, true)) // P: take a screenshot
Renderer::Instance()->TakeScreenshot();
if (CheckKey(GLFW_KEY_V, true)) // V: Starts/Stops recording a camera path
Renderer::Instance()->ToggleRecording();
if (CheckKey(GLFW_KEY_I, true)) // I: Clear the lightpath recording
Renderer::Instance()->ClearLightPath();
if (CheckKey(GLFW_KEY_O, true)) // O: Add node to the lightpath
Renderer::Instance()->AddLightPathNode();
if (CheckKey(GLFW_KEY_T, true))
{
if (CheckKey(GLFW_KEY_LEFT_CONTROL)) // Ctrl + T: Replace recording by rotation recording
Renderer::Instance()->SetRotationRecording();
else // T: Clear the recording
Renderer::Instance()->ClearCameraPath();
}
if (CheckKey(GLFW_KEY_Y, true)) // Y: Add node to the recording path, Ctrl+Y removes the last node from the recording
{
if (CheckKey(GLFW_KEY_LEFT_CONTROL))
Renderer::Instance()->RemoveCameraPathNode();
else
Renderer::Instance()->AddCameraPathNode();
}
if (CheckKey(GLFW_KEY_B, true)) // B: Stores a recording (screenshot at each position along a path)
Renderer::Instance()->StoreRecording();
if (CheckKey(GLFW_KEY_G, true)) // G: Starts/Stops a benchmark (plays back recording and stores all frame times)
Renderer::Instance()->RunBenchmark();
if (CheckKey(GLFW_KEY_N, true)) // N: Stores the current viewpoint to a file
Renderer::Instance()->SaveLastViewpoint();
if (CheckKey(GLFW_KEY_M, true)) // M: Loads the last stored viewpoint
Renderer::Instance()->LoadLastViewpoint();
// 0-9: Go to one of the preset locations from settings
if (CheckKey(GLFW_KEY_0, true)) Renderer::Instance()->SetPresetLocation(0);
if (CheckKey(GLFW_KEY_1, true)) Renderer::Instance()->SetPresetLocation(1);
if (CheckKey(GLFW_KEY_2, true)) Renderer::Instance()->SetPresetLocation(2);
if (CheckKey(GLFW_KEY_3, true)) Renderer::Instance()->SetPresetLocation(3);
if (CheckKey(GLFW_KEY_4, true)) Renderer::Instance()->SetPresetLocation(4);
if (CheckKey(GLFW_KEY_5, true)) Renderer::Instance()->SetPresetLocation(5);
if (CheckKey(GLFW_KEY_6, true)) Renderer::Instance()->SetPresetLocation(6);
if (CheckKey(GLFW_KEY_7, true)) Renderer::Instance()->SetPresetLocation(7);
if (CheckKey(GLFW_KEY_8, true)) Renderer::Instance()->SetPresetLocation(8);
if (CheckKey(GLFW_KEY_9, true)) Renderer::Instance()->SetPresetLocation(9);
}
//************************************
// Check if key is pressed; for lock-sensitive keys only return true if key unlocked
//************************************
bool Controls::CheckKey(int key, bool lock) {
bool result = glfwGetKey(mWindow, key) == GLFW_PRESS && (!lock || !mLocked[key]);
if (glfwGetKey(mWindow, key) == GLFW_RELEASE)
mLocked[key] = false;
if (glfwGetKey(mWindow, key) == GLFW_PRESS)
mLocked[key] = true;
return result;
}
void Controls::Scroll(GLFWwindow* window, double xoffset, double yoffset) {
Controls* controller = Controls::mInstance;
controller->mCamera->UpdateScroll(glm::vec2(xoffset, yoffset), controller->mDeltaTime);
};
Controls::State Controls::GetState() {
return mState;
}
Controls::Controls(GLFWwindow* window, bool fullscreen) {
mWindow = window;
mState = State::RUNNING;//QT
mFullScreen = fullscreen;//QT
mLocked.resize(512);
mMouseX = 0.5;
mMouseY = 0.5;
mDragMouse = true;//QT
mLastTime = 0;
mCurrentTime = 0;
mDeltaTime = 0;
Camera::Create();
mCamera = Camera::Instance();
glfwSetScrollCallback(mWindow, this->Scroll);
}
Controls::~Controls() {
mLocked.clear();
}

51
Research/core/Controls.h Normal file
View File

@@ -0,0 +1,51 @@
#pragma once
#include <vector>
class Camera;
struct GLFWwindow;
class Controls {
public:
enum State { RUNNING, PAUSED, EXIT };
static void Create(GLFWwindow* window, bool fullscreen);
static void Destroy();
static Controls* Instance();
void Run();
State GetState();
protected:
private:
Controls(GLFWwindow* window, bool fullscreen);
~Controls();
void ListenToMouse();
void ListenToKeys();
bool CheckKey(int key, bool lock = false);
static void Scroll(GLFWwindow* window, double xoffset, double yoffset);
static Controls* mInstance;
GLFWwindow* mWindow;
Camera* mCamera;
bool mDragMouse;
State mState;
bool mFullScreen;
std::vector<bool> mLocked; // input is locked for pressed keys to prevent continuous event firing
double mMouseX;
double mMouseY;
double mOldMouseX;
double mOldMouseY;
float mLastTime;
float mCurrentTime;
float mDeltaTime;
static const float RUNNINGSPEEDRATIO;
static const float CRAWLSPEEDRATIO;
static const float SPEEDINCREASERATIO;
};

61
Research/core/Defines.h Normal file
View File

@@ -0,0 +1,61 @@
#pragma once
#define mPi 3.14159265358979323846f
#define mPi2 mPi/2.f
#define mPi3 mPi/3.f
#define mPi4 mPi/4.f
#define mPi6 mPi/6.f
#define mPi8 mPi/8.f
#define mPi10 mPi/10.f
#define m2Pi mPi*2.f
#define m4Pi mPi*4.f
#define mPi_1 1.f/mPi
#define unsigned8 unsigned char
#define unsigned16 unsigned short
#define unsigned32 unsigned int
#define unsigned64 unsigned long long
#define ChildIndex unsigned char
#define FRONT_BOTTOM_LEFT 0
#define FRONT_BOTTOM_RIGHT 1
#define FRONT_TOP_LEFT 2
#define FRONT_TOP_RIGHT 3
#define BACK_BOTTOM_LEFT 4
#define BACK_BOTTOM_RIGHT 5
#define BACK_TOP_LEFT 6
#define BACK_TOP_RIGHT 7
#define TreeType unsigned char
#define STANDARD 0
#define MULTIROOT 1
#define HIERARCHICAL 2
#define ONLYMATERIAL 3
#define UNIQUEINDEX 4
#define BITTREES 5
#define RANDOM 6
// Only allow parallel delete on windows...
#if _WIN32 || _WIN64
#define ALLOW_PARALLEL_DELETE
#endif
// Check windows
#if _WIN32 || _WIN64
#if _WIN64
#define ENVIRONMENT64
#else
#define ENVIRONMENT32
#endif
#endif
// Check GCC
#if __GNUC__
#if __x86_64__ || __ppc64__
#define ENVIRONMENT64
#else
#define ENVIRONMENT32
#endif
#endif

48
Research/core/Hashers.h Normal file
View File

@@ -0,0 +1,48 @@
#pragma once
#include <unordered_map>
#include "Defines.h"
#include "../inc/glm/common.hpp"
#include "BitHelper.h"
namespace std {
// Perfect hash
template<>
struct hash<glm::u8vec3> {
size_t operator()(glm::u8vec3 const &value) const {
return (((size_t) value.x) << 16) + (((size_t) value.y) << 8) + value.z;
}
};
// Perfect hash for 64 bit
template<>
struct hash<glm::u16vec3> {
size_t operator()(glm::u16vec3 const &value) const {
#ifdef ENVIRONMENT64
return (((size_t)value.x) << 32) | (((size_t)value.y) << 16) | (size_t)value.z;
#else
return (((size_t) value.x) << 16) ^ (((size_t) value.y) << 8) ^ (size_t) value.z;
#endif
}
};
template<>
struct hash<glm::u16vec2> {
size_t operator()(glm::u16vec2 const &value) const {
// Perfect hash even for 32 bits
return (size_t) value.x << 16 | value.y;
}
};
template<>
struct hash<glm::uvec3> {
size_t operator()(glm::uvec3 const &value) const {
#ifdef ENVIRONMENT64
return (((size_t)value.x) << 32) ^ (((size_t)value.y) << 16) ^ (size_t)value.z;
#else
return BitHelper::CircularShiftLeft(value.x, unsigned(16)) ^
BitHelper::CircularShiftLeft(value.y, unsigned(8)) ^ value.z;
#endif
}
};
}

View File

@@ -0,0 +1,81 @@
#include "IntersectTests.h"
//************************************
// Check if AABB and triangle intersect using the separating axis theorem
//************************************
bool IntersectTests::BoxTriangleIntersection(glm::vec3 minPosition, glm::vec3 maxPosition, glm::vec3 triangle[3]) {
// Box center and half vector
glm::vec3 c = .5f * (minPosition + maxPosition);
glm::vec3 h = maxPosition - c;
// Translate triangle to center box at origin
glm::vec3 v0 = triangle[0] - c;
glm::vec3 v1 = triangle[1] - c;
glm::vec3 v2 = triangle[2] - c;
// Crossproduct(edge from tri, {x,y,z}-directin), this gives 3x3=9 more tests
glm::vec2 hx = glm::vec2(h.y, h.z);
glm::vec2 hy = glm::vec2(h.x, h.z);
glm::vec2 hz = glm::vec2(h.x, h.y);
glm::vec2 v0x = glm::vec2(v0.y, v0.z);
glm::vec2 v0y = glm::vec2(v0.x, v0.z);
glm::vec2 v0z = glm::vec2(v0.x, v0.y);
glm::vec2 v1x = glm::vec2(v1.y, v1.z);
glm::vec2 v1y = glm::vec2(v1.x, v1.z);
glm::vec2 v1z = glm::vec2(v1.x, v1.y);
glm::vec2 v2x = glm::vec2(v2.y, v2.z);
glm::vec2 v2y = glm::vec2(v2.x, v2.z);
glm::vec2 v2z = glm::vec2(v2.x, v2.y);
// Triangle edges and normal
glm::vec3 e0 = glm::vec3(v1 - v0);
glm::vec3 fe0 = glm::abs(e0);
if (AxisTest(e0.z, e0.y, fe0.z, fe0.y, v0x, v2x, hx) ||
AxisTest(e0.z, e0.x, fe0.z, fe0.x, v0y, v2y, hy) ||
AxisTest(e0.y, e0.x, fe0.y, fe0.x, v1z, v2z, hz))
return false;
glm::vec3 e1 = glm::vec3(v2 - v1);
glm::vec3 fe1 = glm::abs(e1);
if (AxisTest(e1.z, e1.y, fe1.z, fe1.y, v0x, v2x, hx) ||
AxisTest(e1.z, e1.x, fe1.z, fe1.x, v0y, v2y, hy) ||
AxisTest(e1.y, e1.x, fe1.y, fe1.x, v0z, v1z, hz))
return false;
glm::vec3 e2 = glm::vec3(v0 - v2);
glm::vec3 fe2 = glm::abs(e2);
if (AxisTest(e2.z, e2.y, fe2.z, fe2.y, v0x, v1x, hx) ||
AxisTest(e2.z, e2.x, fe2.z, fe2.x, v0y, v1y, hy) ||
AxisTest(e2.y, e2.x, fe2.y, fe2.x, v1z, v2z, hz))
return false;
// Test box against minimal AABB around triangle
glm::vec3 vMin = glm::min(v0, v1);
vMin = glm::min(vMin, v2);
glm::vec3 vMax = glm::max(v0, v1);
vMax = glm::max(vMax, v2);
if (glm::any(glm::greaterThan(vMin, h)) || glm::any(glm::lessThan(vMax, -h)))
return false;
// Test box against triangle plane
glm::vec3 n = glm::cross(e0, e1);
vMin = -glm::sign(n) * h - v0;
vMax = glm::sign(n) * h - v0;
if (glm::dot(n, vMin) > 0.f || glm::dot(n, vMax) < 0.f)
return false;
return true;
}
//************************************
// Help method
//************************************
bool IntersectTests::AxisTest(float a, float b, float fa, float fb, glm::vec2 v0, glm::vec2 v1, glm::vec2 h) {
float p0 = a*v0.x - b*v0.y;
float p1 = a*v1.x - b*v1.y;
float rad = fa * h.x + fb * h.y;
return glm::min(p0, p1) > rad || glm::max(p0, p1) < -rad;
}

View File

@@ -0,0 +1,10 @@
#pragma once
#include "../inc/glm/glm.hpp"
class IntersectTests
{
public:
static bool BoxTriangleIntersection(glm::vec3 minPosition, glm::vec3 maxPosition, glm::vec3 triangle[3]);
private:
static bool AxisTest(float a, float b, float fa, float fb, glm::vec2 v0, glm::vec2 v1, glm::vec2 h);
};

View File

@@ -0,0 +1,22 @@
#include "LightPath.h"
#include "MathHelper.h"
#include "../inc/glm/glm.hpp"
LightState LightStateInterpolator::operator()(const LightState& before, const LightState& after, const double& time)
{
float t = (float)time;
LightState res;
res.lightType = before.lightType;
res.active = t < 0.5 ? before.active : after.active;
if (before.lightType != after.lightType)
res.lightProps = before.lightProps;
else
{
if (res.lightType == LightState::LightType::Directional)
res.lightProps = MathHelper::slerp(t, before.lightProps, after.lightProps);
else if (res.lightType == LightState::LightType::Point)
res.lightProps = MathHelper::lerp(t, before.lightProps, after.lightProps);
}
return res;
};

21
Research/core/LightPath.h Normal file
View File

@@ -0,0 +1,21 @@
#pragma once
#include <string>
#include <vector>
#include "../inc/glm/common.hpp"
#include "../scene/DirectionalLight.h"
#include "../scene/PointLight.h"
#include "Util/Path.h"
struct LightState
{
enum LightType { Point, Directional };
glm::vec3 lightProps;
LightType lightType;
bool active;
};
struct LightStateInterpolator {
LightState operator()(const LightState& before, const LightState& after, const double& time);
};
typedef Path<LightState, LightStateInterpolator> LightPath;

View File

@@ -0,0 +1,39 @@
#pragma once
#include "Defines.h"
#include "../inc/glm/glm.hpp"
class MathHelper
{
public:
// Given a time (t between 0 and 1) and two values, linearly interpolates between the values
template<typename T>
static T lerp(float t, T a, T b)
{
return ((T(1) - t) * a) + (b * t);
}
// Spherical linear interpolation of two vectors (start and end)
static glm::vec3 slerp(float t, glm::vec3 a, glm::vec3 b)
{
// Dot product - the cosine of the angle between 2 vectors.
float dot = glm::dot(a, b);
// Clamp it to be in the range of Acos()
// This may be unnecessary, but floating point
// precision can be a fickle mistress.
glm::clamp(dot, -1.0f, 1.0f);
// Acos(dot) returns the angle between start and end,
// And multiplying that by percent returns the angle between
// start and the final result.
float theta = glm::acos(dot) * t;
glm::vec3 relativeVec = glm::normalize(b - a * dot); // Orthonormal basis
// The final result.
return ((a * glm::cos(theta)) + (relativeVec * glm::sin(theta)));
}
template<typename T>
inline static T DivideRoundUp(T numerator, T denominator)
{
return (numerator / denominator) + (numerator % denominator == 0 ? 0 : 1);
}
};

View File

@@ -0,0 +1,87 @@
#pragma once
#include "BaseOctreeBuilder.h"
#include "../../inc/glm/common.hpp"
#include <unordered_set>
#include "../../core/Hashers.h"
#include "../../scene/Material/Color.h"
#include "../../scene/Material/SmallNormal.h"
#include "../../scene/Material/ColorAndNormal.h"
#include "../../scene/Material/ColorAndNormalAndValue.h"
#include "../../scene/Material/ColorAndOpacity.h"
#include "../Voxelizer/VoxelInfo.h"
template<typename T> struct MaterialAbbreviation { std::string operator()() const { return ""; } };
template<> struct MaterialAbbreviation<Color> { std::string operator()() const { return "c"; } };
template<> struct MaterialAbbreviation<SmallNormal> { std::string operator()() const { return "n"; } };
template<> struct MaterialAbbreviation<ColorAndNormal> { std::string operator()() const { return "cn"; } };
template<> struct MaterialAbbreviation<ColorAndOpacity> { std::string operator()() const { return "co"; } };
template<> struct MaterialAbbreviation<ColorAndNormalAndValue> { std::string operator()() const { return "cnr"; } };
template <typename T> struct MaterialName { std::string operator()() const { return "" } };
template<> struct MaterialName<Color> { std::string operator()() const { return "color"; } };
template<> struct MaterialName<SmallNormal> { std::string operator()() const { return "normal"; } };
template<> struct MaterialName<ColorAndNormal> { std::string operator()() const { return "color and normal"; } };
template<> struct MaterialName<ColorAndOpacity> { std::string operator()() const { return "color and opacity"; } };
template<> struct MaterialName<ColorAndNormalAndValue> { std::string operator()() const { return "color, normal and value"; } };
template<typename T> struct DefaultMaterials { std::vector<T> operator()() const { return std::vector<T>(); } };
template<> struct DefaultMaterials<SmallNormal> { std::vector<SmallNormal> operator()() const { return SmallNormal::GetAll(); } };
template<typename T>
class BaseMaterialOctreeBuilder : public BaseOctreeBuilder
{
public:
BaseMaterialOctreeBuilder() : BaseOctreeBuilder() {}
~BaseMaterialOctreeBuilder() override {}
protected:
T GetMaterial(const VoxelInfo& voxel) const { printf("Error: Material not implemented!"); }
bool RequiresColors() const override { return true; }
bool RequiresNormals() const override { return true; }
bool RequiresReflectivity() const override { return true; }
virtual void PreProcessNode(const glm::uvec3& coordinate, const T& material) {}
void PreProcessNode(const VoxelInfo& voxel) override { PreProcessNode(voxel.position, GetMaterial(voxel)); }
virtual void PreProcessMissingNode(const glm::uvec3& coordinate, const T& material) {}
void PreProcessMissingNode(const VoxelInfo& voxel) override { PreProcessMissingNode(voxel.position, GetMaterial(voxel)); }
// Should add a node to the current pass tree at the given coordinate and color
virtual void AddNode(const glm::uvec3& coordinate, const T& color) = 0;
void AddNode(const VoxelInfo& voxel) override { AddNode(voxel.position, GetMaterial(voxel)); }
virtual void AddMissingNode(const glm::uvec3& coordinate, const T& color) { printf("Warning: Missing nodes not caught!"); }
void AddMissingNode(const VoxelInfo& voxel) override { AddMissingNode(voxel.position, GetMaterial(voxel)); }
private:
};
template<> bool BaseMaterialOctreeBuilder<Color>::RequiresNormals() const { return false; }
template<> bool BaseMaterialOctreeBuilder<Color>::RequiresReflectivity() const { return false; }
template<> Color BaseMaterialOctreeBuilder<Color>::GetMaterial(const VoxelInfo& voxel) const { return Color(voxel.color); }
// Hack to render the normals (debugging)
//template<> BaseMaterialOctreeBuilder<Color>::BaseMaterialOctreeBuilder() { readColors = false; readNormals = true; }
//template<> Color BaseMaterialOctreeBuilder<Color>::GetMaterial(const VoxelInfo& voxel)
//{
// glm::vec3 scaledNormal = SmallNormal(voxel.normal).Get();
// scaledNormal = scaledNormal * 128.0f + 128.f;
// return Color(glm::u8vec3(scaledNormal));
//
//}
template<> bool BaseMaterialOctreeBuilder<SmallNormal>::RequiresColors() const { return false; }
template<> bool BaseMaterialOctreeBuilder<SmallNormal>::RequiresReflectivity() const { return false; }
template<> SmallNormal BaseMaterialOctreeBuilder<SmallNormal>::GetMaterial(const VoxelInfo& voxel) const { return SmallNormal(voxel.normal); }
template<> bool BaseMaterialOctreeBuilder<ColorAndNormal>::RequiresReflectivity() const { return false; }
template<> ColorAndNormal BaseMaterialOctreeBuilder<ColorAndNormal>::GetMaterial(const VoxelInfo& voxel) const {
return ColorAndNormal(voxel.color, voxel.normal);
}
template<> ColorAndNormalAndValue BaseMaterialOctreeBuilder<ColorAndNormalAndValue>::GetMaterial(const VoxelInfo& voxel) const
{
return ColorAndNormalAndValue(voxel.color, NormalAndValue(voxel.normal, (unsigned8)(voxel.reflectivity * 255.0f)));
}
template<> bool BaseMaterialOctreeBuilder<ColorAndOpacity>::RequiresNormals() const { return false; }
template<> ColorAndOpacity BaseMaterialOctreeBuilder<ColorAndOpacity>::GetMaterial(const VoxelInfo& voxel) const
{
return ColorAndOpacity(voxel.color, (unsigned32)(glm::clamp(voxel.reflectivity, 0.f, 1.f) * 65535.f));
}

View File

@@ -0,0 +1,105 @@
#include "BaseOctreeBuilder.h"
#include <stdio.h>
#include <algorithm>
#include "../Voxelizer/VoxelInfo.h"
#include "../Util/Stopwatch.h"
#include "OctreeBuilderStatistics.h"
#include "../Voxelizer/BaseVoxelizer.h"
OctreeBuilderStatistics BaseOctreeBuilder::BuildOctree(BaseVoxelizer& voxelizer, unsigned8 level, unsigned8 maxSingle)
{
// Initialize some variables used for building
unsigned8 singlePassDepth = (maxSingle < level) ? maxSingle : level;
unsigned8 singlePassLevel = level - singlePassDepth;
maxTreeDepth = level;
maxSinglePassLayers = maxSingle;
OctreeBuilderStatistics stats(level);
stats.type = GetTreeType();
Stopwatch watch;
Stopwatch mainWatch; mainWatch.Reset();
// Find out which subtrees to builds
watch.Reset();
mValidCoords = voxelizer.GetValidCoords(singlePassLevel);
std::sort(mValidCoords.begin(), mValidCoords.end(), [&](const glm::uvec3& coord1, const glm::uvec3& coord2) { return SubTreeCompare(coord1, coord2); });
stats.validCoordBuildtime = watch.GetTime();
// Do a pass through all voxels in the scene for preprocessing
watch.Reset();
if (UsePreprocessing())
{
Stopwatch smallWatch;
InitPreprocessing();
unsigned i = 0;
for (const glm::uvec3& coord : mValidCoords)
{
smallWatch.Reset();
if (verbose) printf("Preprocessing subtree %llu / %llu at coordinate (%u, %u, %u).\n", (unsigned64)(i + 1), (unsigned64)(mValidCoords.size()), coord.x, coord.y, coord.z);
InitCurPreprocessPass(coord);
voxelizer.Voxelize(level, singlePassDepth, coord, [&](const VoxelInfo& info, bool best)
{
if (best) PreProcessNode(info);
else PreProcessMissingNode(info);
}, RequiresColors(), RequiresNormals(), RequiresReflectivity());
FinalizeCurPreprocessPass(coord);
if (verbose) printf("Subtree processed in %d ms.\n", (int)(watch.GetTime() * 1000));
i++;
}
FinalizePreprocessing();
}
// Voxelize the scene and build the tree
InitTree();
Stopwatch smallWatch;
unsigned i = 0;
for (const glm::uvec3& coord : mValidCoords)
{
smallWatch.Reset();
if (verbose) printf("Processing subtree %llu / %llu at coordinate (%u, %u, %u).\n", (unsigned64)(i + 1), (unsigned64)(mValidCoords.size()), coord.x, coord.y, coord.z);
if (!IsSinglePass() && !mForceRebuild && CancelCurPassTree(coord))
{
if (verbose) printf("Subtree processing cancelled.\n");
}
else
{
InitCurPassTree(coord);
watch.Reset();
voxelizer.Voxelize(level, singlePassDepth, coord, [&](const VoxelInfo& info, bool best)
{
if (best) AddNode(info);
else AddMissingNode(info);
}, RequiresColors(), RequiresNormals(), RequiresReflectivity());
stats.depthPeelingTime += watch.GetTime(); watch.Reset();
FinalizeCurPassTree(coord);
stats.finalizationTime += watch.GetTime();
if (verbose) printf("Subtree processed in %d ms.\n", (int)(smallWatch.GetTime() * 1000));
}
i++;
}
watch.Reset();
FinalizeTree();
stats.finalizationTime += watch.GetTime();
// Calculate and show statistics
stats.totalTime = mainWatch.GetTime();
stats.octreeNodesPerLevel = GetOctreeNodesPerLevel();
stats.dagNodesPerLevel = GetNodesPerLevel();
if (verbose) stats.Print();
TerminateTree();
return stats;
}
bool BaseOctreeBuilder::SubTreeCompare(const glm::uvec3& coord1, const glm::uvec3& coord2) const
{
if (coord1.z != coord2.z)
return coord1.z < coord2.z;
if (coord1.y != coord2.y)
return coord1.y < coord2.y;
if (coord1.x != coord2.x)
return coord1.x < coord2.x;
return false;
}

View File

@@ -0,0 +1,91 @@
#pragma once
#ifndef GLM_FORCE_RADIANS
#define GLM_FORCE_RADIANS
#endif
#include <vector>
#include "../../inc/glm/glm.hpp"
#include "../../core/Defines.h"
struct VoxelInfo;
struct OctreeBuilderStatistics;
class BaseVoxelizer;
// BaseOctreeBuilder handles octree generation with any base voxelizer.
// Note that this class is abstract and will call several methods that any actual octree builder can implement.
class BaseOctreeBuilder
{
public:
BaseOctreeBuilder() :
mForceRebuild(false)
{}
virtual ~BaseOctreeBuilder() {}
// Given a voxelizer with a loaded scene, buil
OctreeBuilderStatistics BuildOctree(BaseVoxelizer& voxelizer, unsigned8 level, unsigned8 maxSingle);
virtual std::string GetTreeType() = 0;
void SetOutputFile(std::string outputFile) { mOutputFile = outputFile; }
std::string GetOutputFile() const { return mOutputFile; }\
void SetVerbose(bool verbose) { this->verbose = verbose; }
bool GetVerbose() const { return verbose; }
void SetForceRebuild(bool force) { mForceRebuild = force; }
bool GetForceRebuild() const { return mForceRebuild; }
protected:
virtual bool UsePreprocessing() const { return false; }
virtual bool RequiresColors() const = 0;
virtual bool RequiresNormals() const = 0;
virtual bool RequiresReflectivity() const = 0;
// Used to sort the subtrees for optimal building speed (some trees might be quicker to build in a certain order)
// Should return true if the first coord should go before the second
virtual bool SubTreeCompare(const glm::uvec3& coord1, const glm::uvec3& coord2) const;
// Functions to override for preprocessing
virtual bool CancelPreprocessing() { return false; }
virtual void InitPreprocessing() {}
virtual void InitCurPreprocessPass(glm::uvec3 coordinate) {}
virtual void PreProcessNode(const VoxelInfo& voxel) { printf("Warning: PreProcessNode() not implemented!"); }
virtual void PreProcessMissingNode(const VoxelInfo& voxel) {}
virtual void FinalizeCurPreprocessPass(glm::uvec3 coord) {}
virtual void FinalizePreprocessing() {}
// Functions to override for main tree building
virtual void InitTree() = 0;
virtual bool CancelCurPassTree(const glm::uvec3& coord) { return false; }
virtual void InitCurPassTree(glm::uvec3 coord) = 0;
virtual void AddNode(const VoxelInfo& voxel) = 0;
virtual void AddMissingNode(const VoxelInfo& voxel) = 0;
virtual void FinalizeCurPassTree(glm::uvec3 coord) = 0;
virtual void FinalizeTree() = 0;
virtual void TerminateTree() = 0;
virtual std::vector<size_t> GetOctreeNodesPerLevel() = 0;
virtual std::vector<size_t> GetNodesPerLevel() = 0;
// Some getters that are available during construction
// Returns "True" if this tree will be processed in a single pass
bool IsSinglePass() const { return maxSinglePassLayers >= maxTreeDepth; }
// Returns the depth of the main tree
unsigned8 GetTreeDepth() const { return maxTreeDepth; }
// Returns the maximum depth of a tree processing in a single pass
unsigned8 GetSinglePassTreeDepth() const { return maxTreeDepth < maxSinglePassLayers ? maxTreeDepth : maxSinglePassLayers; }
// Returns the level at which subtrees will be appended (e.g. TreeDepth - SinglePassTreeDepth)
unsigned8 GetAppendedTreeLevel() const { return IsSinglePass() ? 0 : (maxTreeDepth - maxSinglePassLayers); }
// Returns all coordinates that contain triangles in this scene.
const std::vector<glm::uvec3>& GetValidCoords() const { return mValidCoords; }
bool verbose;
private:
// Override cancelling of subtree building
bool mForceRebuild;
std::vector<glm::uvec3> mValidCoords;
std::string mOutputFile;
unsigned8 maxSinglePassLayers;
unsigned8 maxTreeDepth;
};

View File

@@ -0,0 +1,23 @@
#pragma once
#include "BaseOctreeBuilder.h"
#include "../../inc/glm/glm.hpp"
#include "../Voxelizer/VoxelInfo.h"
class BaseStandardOctreeBuilder : public BaseOctreeBuilder
{
public:
bool RequiresColors() const override { return false; }
bool RequiresNormals() const override { return false; }
bool RequiresReflectivity() const override { return false; }
protected:
virtual void PreProcessNode(const glm::uvec3& coordinate) {}
void PreProcessNode(const VoxelInfo& voxel) override { PreProcessNode(voxel.position); }
// Should add a node to the current pass tree at the given coordinate and color
virtual void AddNode(const glm::uvec3& coordinate) = 0;
void AddNode(const VoxelInfo& voxel) override { AddNode(voxel.position); }
virtual void AddMissingNode(const glm::uvec3& coordinate) { printf("Warning: Missing nodes not caught!"); }
void AddMissingNode(const VoxelInfo& voxel) override { AddMissingNode(voxel.position); }
private:
};

View File

@@ -0,0 +1,28 @@
#pragma once
#include <map>
#include "../../inc/glm/common.hpp"
#include "../Comparers.h"
#include "ColorQuantizerFactory.h"
#include "../../scene/Material/MaterialQuantizer/ColorAndValueQuantizer.h"
#include "../../scene/Material/SmallNormal.h"
#include "../../scene/Material/BitsMaterial.h"
template<typename T, typename TCompare>
class ColorAndValueQuantizerFactory
{
public:
static ColorAndValueQuantizer<T, TCompare>* Create(std::string quantizerType)
{
BaseColorQuantizer* colorQuantizer = ColorQuantizerFactory::Create(quantizerType);
if (colorQuantizer == NULL) return NULL;
return new ColorAndValueQuantizer<T, TCompare>(colorQuantizer);
}
static std::string GetNormalizedType(std::string quantizerType) { return ColorQuantizerFactory::GetNormalizedType(quantizerType); }
// Returns a string that can be used as a regex to match all color quantizer types and parameters
static std::string GetRegexMatcher() { return ColorQuantizerFactory::GetRegexMatcher(); }
};
typedef ColorAndValueQuantizerFactory<SmallNormal, NormalCompare> ColorAndNormalQuantizerFactory;
typedef ColorAndValueQuantizerFactory<BitsMaterial<16>, BitsMaterialComparer<16>> ColorAndOpacityQuantizerFactory;
typedef ColorAndValueQuantizerFactory<MaterialPair<SmallNormal, BitsMaterial<8>>, MaterialPairCompare<SmallNormal, NormalCompare, BitsMaterial<8>, BitsMaterialComparer<8>>> ColorAndNormalAndValueQuantizerFactory;

View File

@@ -0,0 +1,21 @@
#pragma once
#include "MaterialMultiRootOctreeBuilder.h"
#include "../../scene/Material/ColorChannel.h"
template<>
void MaterialMultiRootOctreeBuilder<ColorChannel>::AddNode(const glm::uvec3& coordinate, const Color& color)
{
mCurPassTree->AddLeafNode(coordinate, ColorChannel());
unsigned8 mask = 0xFF << (8 - mBitsPerChannel);
mCurPassTree->AddLeafNode(coordinate, 0, ColorChannel(color.GetR() & mask));
mCurPassTree->AddLeafNode(coordinate, 1, ColorChannel(color.GetG() & mask));
mCurPassTree->AddLeafNode(coordinate, 2, ColorChannel(color.GetB() & mask));
}
template<>
std::string MaterialMultiRootOctreeBuilder<ColorChannel>::GetTreeType()
{
return "mcc";
}

View File

@@ -0,0 +1,63 @@
#include "ColorQuantizerFactory.h"
#include "../ColorHelper.h"
#include <regex>
#include "../../scene/Material/MaterialQuantizer/ColorQuantizer/BaseColorQuantizer.h"
#include "../../scene/Material/MaterialQuantizer/ColorQuantizer/MaxErrorClusterer.h"
#include "../../scene/Material/MaterialQuantizer/ColorQuantizer/XiangClusterer.h"
#include "../../scene/Material/MaterialQuantizer/ColorQuantizer/XiangCIELABClusterer.h"
float ColorQuantizerFactory::GetMaxCIELABError(std::map<glm::u8vec3, glm::u8vec3, u8vec3comparer>* quantizationMap)
{
float maxError = 0;
for (auto value : *quantizationMap)
{
float error = ColorHelper::GetDeltaEFromRGB(value.first, value.second);
if (error > maxError)
maxError = error;
}
return maxError;
}
BaseColorQuantizer* ColorQuantizerFactory::Create(std::string quantizerType)
{
if (quantizerType == "") return NULL;
std::string maxErrorMatcherRegexStr = "de([0-9]*.[0-9]+|[0-9]+.?)";
std::string xiangLabMatcherRegexStr = "lab([0-9]+)";
std::string xiangMatcherRegexStr = "([0-9]+)";
std::regex maxErrorMatcher(maxErrorMatcherRegexStr);
std::regex xiangLabMatcher(xiangLabMatcherRegexStr);
std::regex xiangMatcher(xiangMatcherRegexStr);
std::smatch sm;
if (std::regex_match(quantizerType, sm, maxErrorMatcher))
{
float maxError = std::stof(sm.str(1));
return new MaxErrorClusterer(maxError);
}
else if (std::regex_match(quantizerType, sm, xiangLabMatcher))
{
unsigned colorCount = std::stoi(sm.str(1));
return new XiangCIELABClusterer(colorCount);
}
else if (std::regex_match(quantizerType, sm, xiangMatcher))
{
unsigned colorCount = std::stoi(sm.str(1));
return new XiangClusterer(colorCount);
}
return NULL;
}
std::string ColorQuantizerFactory::GetNormalizedType(std::string quantizerType)
{
auto quantizer = Create(quantizerType);
if (quantizer == NULL) return "";
std::string normalizedType = quantizer->GetQuantizerDescriptor();
delete quantizer;
return normalizedType;
}
std::string ColorQuantizerFactory::GetRegexMatcher()
{
return "[0-9]+|lab[0-9]+|de([0-9]*.[0-9]+|[0-9]+)";
}

View File

@@ -0,0 +1,17 @@
#pragma once
#include <map>
#include "../../inc/glm/common.hpp"
#include "../Comparers.h"
class BaseColorQuantizer;
class ColorQuantizerFactory
{
public:
static float GetMaxCIELABError(std::map<glm::u8vec3, glm::u8vec3, u8vec3comparer>* quantizationMap);
static BaseColorQuantizer* Create(std::string quantizerType);
static std::string GetNormalizedType(std::string quantizerType);
// Returns a string that can be used as a regex to match all color quantizer types and parameters
static std::string GetRegexMatcher();
};

View File

@@ -0,0 +1,79 @@
#pragma once
#include "../../scene/TextureCompressor/CompressedTexture.h"
#include "../../scene/TextureCompressor/BlockCompressedTexture.h"
#include "../../scene/TextureCompressor/TightlyPackedTexture.h"
#include "../../scene/TextureCompressor/PaletteBlockTexture.h"
#include "../../scene/TextureCompressor/DagBasedTexture.h"
#include "../../scene/TextureCompressor/MultiRootBasedTexture.h"
#include <regex>
enum CompressionType
{
BASIC, BLOCK, TIGHT, TIGHTBLOCK, PALETTEBLOCK, DAGBASED, MULTIROOTBASED
};
template<typename T>
class CompressedTextureFactory
{
public:
static CompressionType GetCompressionType(std::string type)
{
if (type == "b")
return BASIC;
if (type == "p")
return PALETTEBLOCK;
if (type == "d")
return DAGBASED;
if (type == "m")
return MULTIROOTBASED;
if (std::regex_match(type, std::regex("[0-9]+")))
return BLOCK;
if (std::regex_match(type, std::regex("t([0-9]+)")))
return TIGHTBLOCK;
return TIGHT;
}
static CompressedTexture<T>* GetCompressedTexture(std::string type)
{
CompressedTexture<T>* texture = NULL;
std::smatch sm;
if (type == "" || type == "t")
{
texture = new TightlyPackedTexture<T>();
}
else if (type == "b") // b for basic texture (no compression)
{
texture = new BasicTexture<T>();
}
else if (type == "p") // p for palette
{
texture = new PaletteBlockTexture<T>();
}
else if (type == "d")
{
texture = new DagBasedTexture<T>();
}
else if (type == "m")
{
return new MultiRootBasedTexture<T>();
}
else if (std::regex_match(type, sm, std::regex("[0-8]+")))
{
unsigned blockSize = (unsigned)std::stoi(sm.str(0));
texture = new BlockCompressedTexture<T>(blockSize);
}
else if (std::regex_match(type, sm, std::regex("t([0-8]+)")))
{
unsigned blockSize = (unsigned)std::stoi(sm.str(1));
texture = new BlockCompressedTexture<T, TightlyPackedTexture<T>>(blockSize);
}
return texture;
}
// Returns a string that can be used as a regex to match all compressed texture types
static std::string GetRegexMatcher()
{
return std::string("p|b|d|m|[0-9]+|t[0-9]*");
}
};

View File

@@ -0,0 +1,245 @@
#pragma once
#include "BaseMaterialOctreeBuilder.h"
#include "../../inc/glm/common.hpp"
#include <unordered_set>
#include "../../core/Hashers.h"
#include "../../scene/Octree/MaterialLibraryTree.h"
#include "../../scene/Material/MaterialQuantizer/BaseQuantizer.h"
template<typename T, typename Comparer>
class HierarchicalMaterialOctreeBuilder : public BaseMaterialOctreeBuilder<T>
{
public:
HierarchicalMaterialOctreeBuilder(BaseQuantizer<T, Comparer>* quantizer = NULL) :
mTree(NULL),
mMaterialLibrary(NULL),
mReduceMaterials(quantizer != NULL),
mSceneMaterials(std::vector<T>()),
mReplacers(NULL),
mQuantizer(quantizer)
{}
~HierarchicalMaterialOctreeBuilder() override
{
if (mReplacers != NULL)
delete mReplacers;
if (mTree != NULL)
delete mTree;
if (mMaterialLibrary != NULL)
delete mMaterialLibrary;
}
std::string GetTreeType() {
return "h" + MaterialAbbreviation<T>()() +
(mReduceMaterials ? mQuantizer->GetQuantizerDescriptor() : "");
}
protected:
bool MaterialHasDefaults() const { return !DefaultMaterials<T>()().empty(); }
MaterialLibraryTree<T, Comparer, T::CHANNELSPERPIXEL>* CreateTree(unsigned8 depth) const
{
return new MaterialLibraryTree<T, Comparer, T::CHANNELSPERPIXEL>(depth);
}
MaterialLibraryTree<T, Comparer, T::CHANNELSPERPIXEL>* CreateTree(unsigned8 depth, MaterialLibrary<T, Comparer, T::CHANNELSPERPIXEL>* lib) const
{
return new MaterialLibraryTree<T, Comparer, T::CHANNELSPERPIXEL>(depth, lib);
}
std::string GetSinglePassTreeFilename(glm::uvec3 coord)
{
char buffer[255];
sprintf(buffer, "%s_%u_(%u_%u_%u)", GetOutputFile().c_str(), GetTreeDepth(), coord.x, coord.y, coord.z);
return std::string(buffer);
}
bool UsePreprocessing() const override { return !MaterialHasDefaults(); }
void PreProcessNode(const glm::uvec3& coordinate, const T& mat) override { mSceneMaterials.push_back(mat); }
void PreProcessMissingNode(const glm::uvec3& coordinate, const T& mat) override { mSceneMaterials.push_back(mat); }
void FinalizeCurPreprocessPass(glm::uvec3 coord) override { CalculateUniqueSceneMaterials(); }
void InitTree() override
{
// Get scene materials if this is a material type that doesn't need preprocessing
if (mSceneMaterials.empty())
mSceneMaterials = DefaultMaterials<T>()();
if (mReduceMaterials)
{
// Quantize the scene materials
CalculateQuantizedMaterials();
// Store the quantized values in the mSceneMaterials
mSceneMaterials = std::vector<T>();
for (auto it = mReplacers->begin(); it != mReplacers->end(); it++)
mSceneMaterials.push_back(it->second);
CalculateUniqueSceneMaterials();
}
// Initialize the material library
Stopwatch watch; watch.Reset();
if (verbose) printf("Initializing the material library...");
mMaterialLibrary = new MaterialLibrary<T, Comparer, T::CHANNELSPERPIXEL>();
for (auto mat : mSceneMaterials)
mMaterialLibrary->AddMaterial(mat);
mMaterialLibrary->Finalize();
if (verbose) printf("Material library initialized in %u ms.\n", (int)(watch.GetTime() * 1000));
}
void FinalizeTree() override
{
Stopwatch watch;
if (!IsSinglePass())
{
// If this tree was constructred in steps, we should have cache files by now to build the main tree from
unsigned8 mainTreeDepth = GetTreeDepth();
unsigned8 subTreeDepth = GetSinglePassTreeDepth();
unsigned8 mainTreeLevel = mainTreeDepth - subTreeDepth;
mTree = CreateTree(GetTreeDepth(), mMaterialLibrary);
unsigned32 i = 1;
for (const glm::uvec3& coord : GetValidCoords())
{
if (verbose) printf("Reading subtree at %u / %u (%u, %u, %u) from cache...\n", i, (unsigned32)GetValidCoords().size(), coord.x, coord.y, coord.z);
MaterialLibraryTree<T, Comparer, T::CHANNELSPERPIXEL>* subTree = (MaterialLibraryTree<T, Comparer, T::CHANNELSPERPIXEL>*)OctreeLoader::ReadCache(GetTreeType(), GetSinglePassTreeDepth(), GetSinglePassTreeFilename(coord), verbose);
if (verbose) printf("Appending subtree...");
watch.Reset();
mTree->AppendAndMerge(coord, mainTreeLevel, subTree);
delete subTree;
if (verbose) printf("Subtree appended in %d ms.\n", (int)(watch.GetTime() * 1000));
i++;
}
mTree->ClearOrphans();
}
// Propagate the materials
watch.Reset();
if (verbose) printf("Propagating materials in the tree... ");
mTree->PropagateMaterials();
if (verbose) printf("Materials propagated in %d ms.\n", (int)(watch.GetTime() * 1000));
// Generate the material texture
watch.Reset();
if (verbose) printf("Generating material texture... ");
mTree->GetMaterialTexture();
if (verbose) printf("Material texture generated in %d ms\n", (int)(watch.GetTime() * 1000));
// Delete the cache files
if (!IsSinglePass())
{
for (const glm::uvec3& coord : GetValidCoords())
OctreeLoader::DeleteCache(GetTreeType(), GetSinglePassTreeDepth(), GetSinglePassTreeFilename(coord));
}
}
// Step to finalize the main tree (for example storing it to a file)
void TerminateTree() override
{
OctreeLoader::WriteCache(mTree, GetTreeType(), GetOutputFile(), verbose);
delete mTree;
mTree = NULL;
mSceneMaterials.clear();
if (mReplacers != NULL) delete mReplacers;
mReplacers = NULL;
}
bool CancelCurPassTree(const glm::uvec3& coord) override
{
return OctreeLoader::VerifyCache(GetTreeType(), GetSinglePassTreeDepth(), GetSinglePassTreeFilename(coord));
}
// Initialize the tree for the current pass.
void InitCurPassTree(glm::uvec3 coord) override
{
mTree = CreateTree(GetSinglePassTreeDepth(), mMaterialLibrary);
}
// Terminate the tree in the current pass. This means it should also be appended to the main tree and deleted
void FinalizeCurPassTree(glm::uvec3 coord) override
{
Stopwatch watch;
// Remove unused leafs and stuff
mTree->ClearOrphans();
// Convert the subtree to a DAG
if (verbose) printf("Converting subtree to DAG...\n");
watch.Reset();
mTree->ToDAG();
if (verbose) printf("Converting took %u ms.\n", (unsigned)(watch.GetTime() * 1000.0));
if (!IsSinglePass())
{
// Write the subtree to a cache file
OctreeLoader::WriteCache(mTree, GetTreeType(), GetSinglePassTreeFilename(coord), verbose);
delete mTree;
mTree = NULL;
}
}
// Should add a node to the current pass tree at the given coordinate and material
void AddNode(const glm::uvec3& coordinate, const T& mat) override
{
auto replacer = mat;
if (mReduceMaterials)
{
auto replacerPair = mReplacers->find(mat);
if (replacerPair != mReplacers->end())
replacer = replacerPair->second;
else
{
replacer = ParallelNearestFinder<T>()(mat, mSceneMaterials);
mReplacers->insert(std::make_pair(mat, replacer));
}
}
mTree->AddLeafNode(coordinate, replacer);
}
void AddMissingNode(const glm::uvec3& coordinate, const T& mat) override
{
if (!mTree->HasLeaf(coordinate))
AddNode(coordinate, mat);
}
std::vector<size_t> GetOctreeNodesPerLevel() override { return mTree->GetOctreeNodesPerLevel(); }
std::vector<size_t> GetNodesPerLevel() override { return mTree->GetNodesPerLevel(); }
void CalculateUniqueSceneMaterials() { CollectionHelper::Unique<T, Comparer>(mSceneMaterials); }
void CalculateQuantizedMaterials()
{
if (verbose) printf("Quantizing/merging %llu materials...", (unsigned64)(mSceneMaterials.size()));
Stopwatch watch; watch.Reset();
DebugQuantize();
mReplacers = mQuantizer->QuantizeMaterials(mSceneMaterials);
if (verbose) printf("Quantized materials in %d ms.\n", (int)(watch.GetTime() * 1000));
watch.Reset();
}
void DebugQuantize() {}
MaterialLibraryTree<T, Comparer, T::CHANNELSPERPIXEL>* mTree;
bool mReduceMaterials;
std::vector<T> mSceneMaterials;
MaterialLibrary<T, Comparer, T::CHANNELSPERPIXEL>* mMaterialLibrary;
std::map<T, T, Comparer>* mReplacers;
BaseQuantizer<T, Comparer>* mQuantizer;
};
//template<> void HierarchicalMaterialOctreeBuilder<Color, ColorCompare>::DebugQuantize()
//{
// std::vector<std::string> types = { "lab256", "lab1024", "lab4096", "lab16384" };
// for (std::string type : types)
// {
// printf("%s: ", type.c_str());
// BaseColorQuantizer* quantizer = ColorQuantizerFactory::Create(type);
// auto temp = quantizer->QuantizeMaterials(mSceneMaterials);
// delete temp;
// }
//}
template<> bool HierarchicalMaterialOctreeBuilder<SmallNormal, NormalCompare>::MaterialHasDefaults() const { return false; }
template<> void HierarchicalMaterialOctreeBuilder<ColorAndNormal, ColorAndNormalCompare>::PreProcessMissingNode(const glm::uvec3& coordinate, const ColorAndNormal& mat)
{
mSceneMaterials.push_back(mat);
}

View File

@@ -0,0 +1,233 @@
#include "MaterialLibraryMultiRootOctreeBuilder.h"
#include "../Util/Stopwatch.h"
#include "OctreeLoader.h"
#include "../CollectionHelper.h"
#include "../../inc/tbb/parallel_for.h"
#include "../../inc/tbb/concurrent_queue.h"
MaterialLibraryMultiRootOctreeBuilder::MaterialLibraryMultiRootOctreeBuilder(BaseQuantizer<Color, ColorCompare>* quantizer) :
BaseMaterialOctreeBuilder(),
mTree(NULL),
mIntermediateTree(NULL),
mQuantizeColors(quantizer != NULL),
mQuantizer(quantizer),
mSceneColors(std::vector<Color>()),
mColorReplacers(std::unordered_map<Color, Color>())
{
// TODO: when building in steps, use preprocessing to find the materials in the upper levels
}
MaterialLibraryMultiRootOctreeBuilder::~MaterialLibraryMultiRootOctreeBuilder() {}
bool MaterialLibraryMultiRootOctreeBuilder::IsLimitedColors() const { return mQuantizeColors || !IsSinglePass(); }
bool MaterialLibraryMultiRootOctreeBuilder::UsePreprocessing() const { return IsLimitedColors(); }
std::string MaterialLibraryMultiRootOctreeBuilder::GetTreeType() { return "blc" + (mQuantizer == NULL ? "" : mQuantizer->GetQuantizerDescriptor()); }
void MaterialLibraryMultiRootOctreeBuilder::InitTree()
{
mTree = new MaterialLibraryMultiRoot<Color, ColorCompare>(GetTreeDepth());
}
void MaterialLibraryMultiRootOctreeBuilder::FinalizeTree()
{
// Store the amount of nodes the octree had for the first few levels
auto nodesPerLevel = mTree->GetOctreeNodesPerLevel();
}
void MaterialLibraryMultiRootOctreeBuilder::TerminateTree()
{
OctreeLoader::WriteCache(mTree, GetTreeType(), GetOutputFile(), verbose);
delete mTree;
mSceneColors.clear();
mColorReplacers.clear();
}
void MaterialLibraryMultiRootOctreeBuilder::InitCurPassTree(glm::uvec3 coord)
{
mIntermediateTree = new MaterialTree<Color, ColorCompare>(GetSinglePassTreeDepth());
mIntermediateTree->UseLeafMap(true);
//for (auto color : mSceneColors)
// mIntermediateTree->AddMaterial(Color(color));
//mIntermediateTree->FinalizeMaterials();
}
void MaterialLibraryMultiRootOctreeBuilder::FinalizeCurPassTree(glm::uvec3 coord)
{
Stopwatch watch;
if (mIntermediateTree->GetNodeCount() > 1) // Only append the tree (and compress) if it is not empty
{
// Convert the intermediate tree to a DAG before building the material library multiroot tree:
if (verbose) printf("Converting intermediate tree to a DAG...\n");
watch.Reset();
mIntermediateTree->ToDAG();
if (verbose) printf("Converting took %d ms.\n", (int)(watch.GetTime() * 1000));
// Propagate the materials in the intermediate tree
if (verbose) printf("Propagating materials in the intermediate tree...");
watch.Reset();
mIntermediateTree->PropagateMaterials(Color::WeightedAverage);
if (verbose) printf("Propagated in %d ms.\n", (int)(watch.GetTime() * 1000));
// Quantize the colors in the material tree
if (IsLimitedColors())
{
if (verbose) printf("Replacing materials by their quantized counterparts.");
std::vector<Color> curPassMaterials = mIntermediateTree->GetUniqueMaterials();
CollectionHelper::Unique(curPassMaterials, ColorCompare());
std::vector<Color> curPassQuantizedMaterials(curPassMaterials.size());
if (verbose) printf(".");
// For each material in the curPassMaterials, find the closest material
tbb::concurrent_queue<size_t> newReplacers;
tbb::parallel_for(size_t(0), curPassMaterials.size(), [&](const size_t& i)
{
auto cachedReplacer = mColorReplacers.find(curPassMaterials[i]);
if (cachedReplacer != mColorReplacers.end())
curPassQuantizedMaterials[i] = cachedReplacer->second;
else
{
curPassQuantizedMaterials[i] = NearestFinder<Color>()(curPassMaterials[i], mSceneColors);
newReplacers.push(i);
}
});
// Add the newly found replacers to the cache
for (auto i = newReplacers.unsafe_begin(); i != newReplacers.unsafe_end(); ++i)
mColorReplacers.insert(std::pair<Color, Color>(curPassMaterials[*i], curPassQuantizedMaterials[*i]));
// Update the current scene color map
std::unordered_map<Color, Color> quantizedColors;
for (size_t i = 0; i < curPassMaterials.size(); i++)
quantizedColors.insert(std::pair<Color, Color>(curPassMaterials[i], curPassQuantizedMaterials[i]));
if (verbose) printf(".");
mIntermediateTree->ReplaceMaterials(quantizedColors);
if (verbose) printf("Replaced in %d ms.\n", (int)(watch.GetTime() * 1000));
if (verbose) printf("%llu new materials quantized, cache now contains %llu materials.\n", (unsigned64)newReplacers.unsafe_size(), (unsigned64)mColorReplacers.size());
}
// Build the actual MaterialLibaryMultiRootTree based on the intermediate tree
if (verbose) printf("Building multiroot tree based on intermediate tree...");
watch.Reset();
auto curPassTree = new MaterialLibraryMultiRoot<Color, ColorCompare>(mIntermediateTree->GetMaxLevel());
if (IsLimitedColors()) curPassTree->CreateMaterialLibrary(mSceneColors);
curPassTree->BaseOn(mIntermediateTree, false);
delete mIntermediateTree;
curPassTree->ShaveEquals();
curPassTree->ToDAG();
curPassTree->FillEmptySpace(false);
if (verbose) printf("Multiroot tree build in %d ms.\n", (int)(watch.GetTime() * 1000));
// Convert the current pass tree to a DAG
if (verbose) printf("Converting the current pass multiroot tree to a DAG...\n");
watch.Reset();
curPassTree->ToDAG();
if (verbose) printf("Converted in %d ms.\n", (int)(watch.GetTime() * 1000));
auto octreeNodesPerLevel = curPassTree->GetOctreeNodesPerLevel();
if (IsSinglePass()) // Means we just constructed the root, so no need to append
{
delete mTree;
mTree = curPassTree;
}
else
{
if (verbose) printf("Appending subtree... ");
watch.Reset();
mTree->Append(coord, GetAppendedTreeLevel(), curPassTree);
delete curPassTree;
if (verbose) printf("Appending took %d ms.\n", (int)(watch.GetTime() * 1000));
if (verbose) printf("Converting current tree to DAG...\n");
watch.Reset();
mTree->ToDAG(GetAppendedTreeLevel());
if (verbose) printf("Converted in %d ms.\n", (int)(watch.GetTime() * 1000));
}
}
else
{
delete mIntermediateTree;
}
}
void MaterialLibraryMultiRootOctreeBuilder::AddMissingNode(const glm::uvec3& coordinate, const Color& color)
{
if (!mIntermediateTree->HasLeaf(coordinate))
AddNode(coordinate, color);
}
void MaterialLibraryMultiRootOctreeBuilder::AddNode(const glm::uvec3& coordinate, const Color& color)
{
if (IsLimitedColors())
{
auto replacer = mColorReplacers.find(color);
if (replacer == mColorReplacers.end())
{
Color replacement = NearestFinder<Color>()(color, mSceneColors);
mColorReplacers.insert(std::pair<Color, Color>(color, replacement));
replacer = mColorReplacers.find(color);
}
assert(replacer != mColorReplacers.end());
mIntermediateTree->AddLeafNode(coordinate, replacer->second);
}
else
{
mIntermediateTree->AddLeafNode(coordinate, Color(color));
}
}
//-----------------------------------------------------------------------------------
// ---------------------------------PREPROCESSING------------------------------------
//-----------------------------------------------------------------------------------
void MaterialLibraryMultiRootOctreeBuilder::PreProcessNode(const glm::uvec3& coordinate, const Color& color)
{
mSceneColors.push_back(color);
}
void MaterialLibraryMultiRootOctreeBuilder::FinalizePreprocessing()
{
CalculateUniqueSceneColors();
if (mQuantizer != NULL)
{
if (verbose) printf("Quantizing %llu materials...", (unsigned64)mSceneColors.size());
Stopwatch watch; watch.Reset();
auto quantizedMaterials = mQuantizer->QuantizeMaterials(mSceneColors);
mSceneColors.clear();
for (auto quantizedMaterial : *quantizedMaterials)
{
mColorReplacers.insert(std::pair<Color, Color>(quantizedMaterial.first, quantizedMaterial.second));
mSceneColors.push_back(quantizedMaterial.second);
}
CalculateUniqueSceneColors();
if (verbose) printf("Quantized in %u ms, %llu materials left\n", (unsigned)(watch.GetTime() * 1000), (unsigned64)mSceneColors.size());
}
else
{
for (Color color : mSceneColors)
mColorReplacers.insert(std::pair<Color, Color>(color, color));
}
}
void MaterialLibraryMultiRootOctreeBuilder::CalculateUniqueSceneColors()
{
// Remove duplicates from scene colors
CollectionHelper::Unique(mSceneColors, ColorCompare());
}
//-----------------------------------------------------------------------------------
// -----------------------------------STATISTICS-------------------------------------
//-----------------------------------------------------------------------------------
std::vector<size_t> MaterialLibraryMultiRootOctreeBuilder::GetOctreeNodesPerLevel()
{
return mTree->GetOctreeNodesPerLevel();
}
std::vector<size_t> MaterialLibraryMultiRootOctreeBuilder::GetNodesPerLevel()
{
return mTree->GetNodesPerLevel();
}

View File

@@ -0,0 +1,50 @@
#pragma once
#include "BaseMaterialOctreeBuilder.h"
#include "../../scene/Material/Color.h"
#include "../../scene/Octree/MaterialLibraryMultiRootTree.h"
#include "../../scene/Octree/MaterialTree.h"
#include "../Comparers.h"
#include "../../scene/Material/MaterialQuantizer/BaseQuantizer.h"
class MaterialLibraryMultiRootOctreeBuilder : public BaseMaterialOctreeBuilder<Color>
{
public:
MaterialLibraryMultiRootOctreeBuilder(BaseQuantizer<Color, ColorCompare>* quantizer = NULL);
~MaterialLibraryMultiRootOctreeBuilder() override;
std::string GetTreeType() override;
protected:
// Initialize the main tree
void InitTree() override;
void FinalizeTree() override;
// Step to finalize the main tree (for example storing it to a file)
void TerminateTree() override;
bool IsLimitedColors() const;
bool UsePreprocessing() const override;
// Initialize the tree for the current pass.
void InitCurPassTree(glm::uvec3 coord) override;
// Terminate the tree in the current pass. This means it should also be appended to the main tree and deleted
void FinalizeCurPassTree(glm::uvec3 coord) override;
// Should add a node to the current pass tree at the given coordinate and color
void AddNode(const glm::uvec3& coordinate, const Color& color) override;
void AddMissingNode(const glm::uvec3& coordinate, const Color& color) override;
void PreProcessNode(const glm::uvec3& coordinate, const Color& color) override;
void FinalizePreprocessing() override;
void CalculateUniqueSceneColors();
std::vector<size_t> GetOctreeNodesPerLevel() override;
std::vector<size_t> GetNodesPerLevel() override;
private:
MaterialLibraryMultiRoot<Color, ColorCompare>* mTree;
MaterialTree<Color, ColorCompare>* mIntermediateTree;
bool mQuantizeColors;
BaseQuantizer<Color, ColorCompare>* mQuantizer;
std::vector<Color> mSceneColors;
std::unordered_map<Color, Color> mColorReplacers;
};

View File

@@ -0,0 +1,113 @@
#pragma once
#include "BaseMaterialOctreeBuilder.h"
#include "../../scene/Octree/LeafMaterialMultiRootTree.h"
#include "../Util/Stopwatch.h"
#include "OctreeLoader.h"
template <typename T>
class MaterialMultiRootOctreeBuilder : public BaseMaterialOctreeBuilder<Color>
{
private:
LeafMaterialMultiRootTree<T>* mTree;
LeafMaterialMultiRootTree<T>* mCurPassTree;
unsigned8 mBitsPerChannel;
std::string mTreeType;
public:
MaterialMultiRootOctreeBuilder(std::string treeType, unsigned8 bitsPerChannel) :
BaseMaterialOctreeBuilder(),
mTree(NULL),
mCurPassTree(NULL),
mBitsPerChannel(bitsPerChannel),
mTreeType(treeType)
{}
MaterialMultiRootOctreeBuilder(std::string treeType) : MaterialMultiRootOctreeBuilder(treeType, 8) {}
~MaterialMultiRootOctreeBuilder() override {}
std::string GetTreeType() override { bool explicitSpecializationGiven = false; assert(explicitSpecializationGiven); return ""; }
protected:
// Initialize the main tree
void InitTree() override
{
mTree = (LeafMaterialMultiRootTree<T>*)OctreeLoader::CreateTree(mTreeType, GetTreeDepth());
}
void FinalizeTree() override
{
// Convert the final tree to a DAG
if (verbose) printf("Converting final tree to DAG...\n");
Stopwatch watch; watch.Reset();
mTree->ToDAG();
if (verbose) printf("Done in %u ms, %llu nodes left.\n", (unsigned)(watch.GetTime() * 1000), (unsigned64)mTree->GetNodeCount());
}
// Step to finalize the main tree (for example storing it to a file)
void TerminateTree() override
{
OctreeLoader::WriteCache(mTree, GetTreeType(), GetOutputFile(), verbose);
delete mTree;
}
// Initialize the tree for the current pass.
void InitCurPassTree(glm::uvec3 coord) override
{
mCurPassTree = (LeafMaterialMultiRootTree<T>*)OctreeLoader::CreateTree(mTreeType, GetSinglePassTreeDepth());
}
// Terminate the tree in the current pass. This means it should also be appended to the main tree and deleted
void FinalizeCurPassTree(glm::uvec3 coord) override
{
Stopwatch watch;
if (mCurPassTree->GetNodeCount() > 1) // Only append the tree (and compress) if it is not empty
{
if (IsSinglePass()) // Means we just constructed the root, so no need to append
{
delete mTree;
mTree = mCurPassTree;
}
else
{
// Convert the subtree to a DAG first, this saved time when appending and converting the total tree
// Benchmark (Total build time for subtrees of depth 10, final tree of depth 12, Release mode with pool):
// 209.922 seconds without early converting
// 163.645 seconds with early converting
if (verbose) printf("Converting subtree to DAG...\n");
watch.Reset();
mCurPassTree->ToDAG();
if (verbose) printf("Converting took %d ms.\n", (int)(watch.GetTime() * 1000));
if (verbose) printf("Appending subtree... ");
mTree->Append(coord, GetAppendedTreeLevel(), mCurPassTree);
delete mCurPassTree;
if (verbose) printf("Converting current tree to DAG...\n");
mTree->ToDAG(GetAppendedTreeLevel());
}
}
else
{
delete mCurPassTree;
}
}
void AddMissingNode(const glm::uvec3& coordinate, const Color& color) override
{
if (!mCurPassTree->HasLeaf(coordinate))
AddNode(coordinate, color);
}
// Should add a node to the current pass tree at the given coordinate and color
void AddNode(const glm::uvec3& coordinate, const Color& color) override
{
((Root*)mCurPassTree)->AddLeafNode(coordinate);
}
std::vector<size_t> GetOctreeNodesPerLevel() override { return mTree->GetOctreeNodesPerLevel(); }
std::vector<size_t> GetNodesPerLevel() override { return mTree->GetNodesPerLevel(); }
};

View File

@@ -0,0 +1,151 @@
#pragma once
#include "MaterialMultiRootOctreeBuilder.h"
#include "../../scene/Octree/MultiRootBitsTree.h"
#include "../BitHelper.h"
template<>
void MaterialMultiRootOctreeBuilder<BitsMaterial<1>>::AddNode(const glm::uvec3& coordinate, const Color& color)
{
mCurPassTree->AddLeafNode(coordinate, BitsMaterial<1>(1));
for (unsigned8 c = 0; c < 3; c++)
for (unsigned8 i = 0; i < mBitsPerChannel; i++)
{
auto material = BitsMaterial<1>(color[c], i);
if (material.GetValue() != 0)
mCurPassTree->AddLeafNode(coordinate, mBitsPerChannel * c + i, material);
}
}
template<>
void MaterialMultiRootOctreeBuilder<BitsMaterial<2>>::AddNode(const glm::uvec3& coordinate, const Color& color)
{
unsigned N = 2;
mCurPassTree->AddLeafNode(coordinate, BitsMaterial<2>(1));
unsigned treesPerChannel = mBitsPerChannel / N + ((mBitsPerChannel % N) != 0 ? 1 : 0);
unsigned8 mask = BitHelper::GetLSMaskUntil<unsigned8>(8 - mBitsPerChannel);
for (unsigned8 c = 0; c < 3; c++)
{
unsigned8 maskedColor = color[c] & mask;
for (unsigned8 i = 0; i < treesPerChannel; i++)
{
auto material = BitsMaterial<2>(maskedColor, N * i);
if (material.GetValue() != 0)
mCurPassTree->AddLeafNode(coordinate, treesPerChannel * c + i, material);
}
}
}
template<>
void MaterialMultiRootOctreeBuilder<BitsMaterial<3>>::AddNode(const glm::uvec3& coordinate, const Color& color)
{
unsigned N = 3;
mCurPassTree->AddLeafNode(coordinate, BitsMaterial<3>(1));
unsigned treesPerChannel = mBitsPerChannel / N + ((mBitsPerChannel % N) != 0 ? 1 : 0);
unsigned8 mask = BitHelper::GetLSMaskUntil<unsigned8>(8 - mBitsPerChannel);
for (unsigned8 c = 0; c < 3; c++)
{
unsigned8 maskedColor = color[c] & mask;
for (unsigned8 i = 0; i < treesPerChannel; i++)
{
auto material = BitsMaterial<3>(maskedColor, N * i);
if (material.GetValue() != 0)
mCurPassTree->AddLeafNode(coordinate, treesPerChannel * c + i, material);
}
}
}
template<>
void MaterialMultiRootOctreeBuilder<BitsMaterial<4>>::AddNode(const glm::uvec3& coordinate, const Color& color)
{
unsigned N = 4;
mCurPassTree->AddLeafNode(coordinate, BitsMaterial<4>(1));
unsigned treesPerChannel = mBitsPerChannel / N + ((mBitsPerChannel % N) != 0 ? 1 : 0);
unsigned8 mask = BitHelper::GetLSMaskUntil<unsigned8>(8 - mBitsPerChannel);
for (unsigned8 c = 0; c < 3; c++)
{
unsigned8 maskedColor = color[c] & mask;
for (unsigned8 i = 0; i < treesPerChannel; i++)
{
auto material = BitsMaterial<4>(maskedColor, N * i);
if (material.GetValue() != 0)
mCurPassTree->AddLeafNode(coordinate, treesPerChannel * c + i, material);
}
}
}
template<>
void MaterialMultiRootOctreeBuilder<BitsMaterial<5>>::AddNode(const glm::uvec3& coordinate, const Color& color)
{
unsigned N = 5;
mCurPassTree->AddLeafNode(coordinate, BitsMaterial<5>(1));
unsigned treesPerChannel = mBitsPerChannel / N + ((mBitsPerChannel % N) != 0 ? 1 : 0);
unsigned8 mask = BitHelper::GetLSMaskUntil<unsigned8>(8 - mBitsPerChannel);
for (unsigned8 c = 0; c < 3; c++)
{
unsigned8 maskedColor = color[c] & mask;
for (unsigned8 i = 0; i < treesPerChannel; i++)
{
auto material = BitsMaterial<5>(maskedColor, N * i);
if (material.GetValue() != 0)
mCurPassTree->AddLeafNode(coordinate, treesPerChannel * c + i, material);
}
}
}
template<>
void MaterialMultiRootOctreeBuilder<BitsMaterial<6>>::AddNode(const glm::uvec3& coordinate, const Color& color)
{
unsigned N = 6;
mCurPassTree->AddLeafNode(coordinate, BitsMaterial<6>(1));
unsigned treesPerChannel = mBitsPerChannel / N + ((mBitsPerChannel % N) != 0 ? 1 : 0);
unsigned8 mask = BitHelper::GetLSMaskUntil<unsigned8>(8 - mBitsPerChannel);
for (unsigned8 c = 0; c < 3; c++)
{
unsigned8 maskedColor = color[c] & mask;
for (unsigned8 i = 0; i < treesPerChannel; i++)
{
auto material = BitsMaterial<6>(maskedColor, N * i);
if (material.GetValue() != 0)
mCurPassTree->AddLeafNode(coordinate, treesPerChannel * c + i, material);
}
}
}
template<>
void MaterialMultiRootOctreeBuilder<BitsMaterial<7>>::AddNode(const glm::uvec3& coordinate, const Color& color)
{
unsigned N = 7;
mCurPassTree->AddLeafNode(coordinate, BitsMaterial<7>(1));
unsigned treesPerChannel = mBitsPerChannel / N + ((mBitsPerChannel % N) != 0 ? 1 : 0);
unsigned8 mask = BitHelper::GetLSMaskUntil<unsigned8>(8 - mBitsPerChannel);
for (unsigned8 c = 0; c < 3; c++)
{
unsigned8 maskedColor = color[c] & mask;
for (unsigned8 i = 0; i < treesPerChannel; i++)
{
auto material = BitsMaterial<7>(maskedColor, N * i);
if (material.GetValue() != 0)
mCurPassTree->AddLeafNode(coordinate, treesPerChannel * c + i, material);
}
}
}
template<>
void MaterialMultiRootOctreeBuilder<BitsMaterial<8>>::AddNode(const glm::uvec3& coordinate, const Color& color)
{
mCurPassTree->AddLeafNode(coordinate, BitsMaterial<8>());
unsigned8 mask = BitHelper::GetLSMaskUntil<unsigned8>(8 - mBitsPerChannel);
mCurPassTree->AddLeafNode(coordinate, 0, BitsMaterial<8>(color.GetR() & mask));
mCurPassTree->AddLeafNode(coordinate, 1, BitsMaterial<8>(color.GetG() & mask));
mCurPassTree->AddLeafNode(coordinate, 2, BitsMaterial<8>(color.GetB() & mask));
}
template<> std::string MaterialMultiRootOctreeBuilder<BitsMaterial<1>>::GetTreeType() { return "m" + std::to_string(mBitsPerChannel) + "b1"; }
template<> std::string MaterialMultiRootOctreeBuilder<BitsMaterial<2>>::GetTreeType() { return "m" + std::to_string(mBitsPerChannel) + "b2"; }
template<> std::string MaterialMultiRootOctreeBuilder<BitsMaterial<3>>::GetTreeType() { return "m" + std::to_string(mBitsPerChannel) + "b3"; }
template<> std::string MaterialMultiRootOctreeBuilder<BitsMaterial<4>>::GetTreeType() { return "m" + std::to_string(mBitsPerChannel) + "b4"; }
template<> std::string MaterialMultiRootOctreeBuilder<BitsMaterial<5>>::GetTreeType() { return "m" + std::to_string(mBitsPerChannel) + "b5"; }
template<> std::string MaterialMultiRootOctreeBuilder<BitsMaterial<6>>::GetTreeType() { return "m" + std::to_string(mBitsPerChannel) + "b6"; }
template<> std::string MaterialMultiRootOctreeBuilder<BitsMaterial<7>>::GetTreeType() { return "m" + std::to_string(mBitsPerChannel) + "b7"; }
template<> std::string MaterialMultiRootOctreeBuilder<BitsMaterial<8>>::GetTreeType() { return "m" + std::to_string(mBitsPerChannel) + "b8"; }

View File

@@ -0,0 +1,120 @@
#include "MultiRootOctreeBuilder.h"
#include "../../scene/Octree/MultiRootTree.h"
#include "../Util/Stopwatch.h"
#include "OctreeLoader.h"
MultiRootOctreeBuilder::MultiRootOctreeBuilder(unsigned8 bitsPerChannel) :
BaseMaterialOctreeBuilder(),
mTree(NULL),
mCurPassTree(NULL),
mBitsPerChannel(bitsPerChannel)
{}
MultiRootOctreeBuilder::MultiRootOctreeBuilder() : MultiRootOctreeBuilder(8)
{}
MultiRootOctreeBuilder::~MultiRootOctreeBuilder() {}
std::string MultiRootOctreeBuilder::GetTreeType() { return "m" + std::to_string(mBitsPerChannel); }
void MultiRootOctreeBuilder::InitTree()
{
mTree = new MultiRootTree<>(GetTreeDepth(), 3 * mBitsPerChannel);
}
void MultiRootOctreeBuilder::FinalizeTree()
{
// Convert the final tree to a DAG
Stopwatch watch;
if (verbose) printf("Converting final tree to DAG...\n");
watch.Reset();
mTree->ToDAG();
if (verbose) printf("Done in %u ms, %llu nodes left.\n", (unsigned)(watch.GetTime() * 1000), (unsigned64)mTree->GetNodeCount());
}
void MultiRootOctreeBuilder::TerminateTree()
{
OctreeLoader::WriteCache(mTree, GetTreeType(), GetOutputFile(), verbose);
delete mTree;
}
void MultiRootOctreeBuilder::InitCurPassTree(glm::uvec3 coord)
{
mCurPassTree = new MultiRootTree<>(GetSinglePassTreeDepth(), 3 * mBitsPerChannel);
}
void MultiRootOctreeBuilder::FinalizeCurPassTree(glm::uvec3 coord)
{
Stopwatch watch;
if (mCurPassTree->GetNodeCount() > 1) // Only append the tree (and compress) if it is not empty
{
if (IsSinglePass()) // Means we just constructed the root, so no need to append
{
delete mTree;
mTree = mCurPassTree;
}
else
{
// Convert the subtree to a DAG first, this saved time when appending and converting the total tree
// Benchmark (Total build time for subtrees of depth 10, final tree of depth 12, Release mode with pool):
// 209.922 seconds without early converting
// 163.645 seconds with early converting
if (verbose) printf("Converting subtree to DAG...\n");
watch.Reset();
mCurPassTree->ToDAG();
if (verbose) printf("Converting took %d ms.\n", (int)(watch.GetTime() * 1000));
if (verbose) printf("Appending subtree... ");
mTree->Append(coord, GetAppendedTreeLevel(), mCurPassTree);
delete mCurPassTree;
if (verbose) printf("Converting current tree to DAG...\n");
mTree->ToDAG(GetAppendedTreeLevel());
}
}
else
{
delete mCurPassTree;
}
}
void MultiRootOctreeBuilder::UpdateMultiRoot(glm::uvec3 coord, glm::u8 color, unsigned32 slaveRootOffset)
{
//glm::u8 testColor = 0;
// Add nodes to the tree for the color
for (unsigned8 i = 0; i < mBitsPerChannel; i++)
{
glm::u8 mask = 1 << i;
if ((color & mask) == mask)
{
mCurPassTree->AddLeafNode(coord, slaveRootOffset + i);
//testColor += mask;
}
}
}
void MultiRootOctreeBuilder::AddMissingNode(const glm::uvec3& coordinate, const Color& color)
{
if (!mCurPassTree->HasLeaf(coordinate))
AddNode(coordinate, color);
}
void MultiRootOctreeBuilder::AddNode(const glm::uvec3& coordinate, const Color& color)
{
mCurPassTree->AddLeafNode(coordinate);
UpdateMultiRoot(coordinate, color.GetR(), 0);
UpdateMultiRoot(coordinate, color.GetG(), mBitsPerChannel);
UpdateMultiRoot(coordinate, color.GetB(), 2 * mBitsPerChannel);
}
std::vector<size_t> MultiRootOctreeBuilder::GetOctreeNodesPerLevel()
{
return mTree->GetOctreeNodesPerLevel();
}
std::vector<size_t> MultiRootOctreeBuilder::GetNodesPerLevel()
{
return mTree->GetNodesPerLevel();
}

View File

@@ -0,0 +1,40 @@
#pragma once
#include "BaseMaterialOctreeBuilder.h"
#include "../../scene/Octree/MultiRootTree.h"
class MultiRootOctreeBuilder : public BaseMaterialOctreeBuilder<Color>
{
public:
MultiRootOctreeBuilder();
MultiRootOctreeBuilder(unsigned8 bitsPerChannel);
~MultiRootOctreeBuilder() override;
std::string GetTreeType() override;
protected:
// Initialize the main tree
void InitTree() override;
void FinalizeTree() override;
// Step to finalize the main tree (for example storing it to a file)
void TerminateTree() override;
// Initialize the tree for the current pass.
void InitCurPassTree(glm::uvec3 coord) override;
// Terminate the tree in the current pass. This means it should also be appended to the main tree and deleted
void FinalizeCurPassTree(glm::uvec3 coord) override;
void AddMissingNode(const glm::uvec3& coordinate, const Color& color) override;
// Should add a node to the current pass tree at the given coordinate and color
void AddNode(const glm::uvec3& coordinate, const Color& color) override;
std::vector<size_t> GetOctreeNodesPerLevel() override;
std::vector<size_t> GetNodesPerLevel() override;
private:
void UpdateMultiRoot(glm::uvec3 coordinate, glm::u8 color, unsigned32 slaveRootOffset);
MultiRootTree<>* mTree;
MultiRootTree<>* mCurPassTree;
unsigned8 mBitsPerChannel;
};

View File

@@ -0,0 +1,24 @@
#include "NormalQuantizerFactory.h"
#include "../../scene/Material/MaterialQuantizer/NormalQuantizer.h"
BaseQuantizer<SmallNormal, NormalCompare>* NormalQuantizerFactory::Create(std::string quantizerType)
{
if (quantizerType == "") return NULL;
unsigned8 bits = std::stoi(quantizerType);
return new NormalQuantizer(bits);
}
std::string NormalQuantizerFactory::GetNormalizedType(std::string quantizerType)
{
auto quantizer = Create(quantizerType);
if (quantizer == NULL) return "";
std::string normalizedType = quantizer->GetQuantizerDescriptor();
delete quantizer;
return normalizedType;
}
std::string NormalQuantizerFactory::GetRegexMatcher()
{
return "4|6|8|10|12|14|16|18|20|22|24|26|28|30|32";
}

View File

@@ -0,0 +1,18 @@
#pragma once
#include <map>
#include "../../inc/glm/common.hpp"
#include "../../scene/Material/MaterialQuantizer/BaseQuantizer.h"
#include "../../scene/Material/SmallNormal.h"
typedef BaseQuantizer<SmallNormal, NormalCompare> BaseNormalQuantizer;
class NormalQuantizerFactory
{
public:
static BaseNormalQuantizer* Create(std::string quantizerType);
static std::string GetNormalizedType(std::string quantizerType);
// Returns a string that can be used as a regex to match all normal quantizer types and parameters
static std::string GetRegexMatcher();
};

View File

@@ -0,0 +1,217 @@
#include "OctreeBuilder.h"
#include <regex>
#include "TreeTypeParser.h"
#include "SettingsParser.h"
#include "../PathHelper.h"
#include "../StringHelper.h"
#include "../../scene/Material/Color.h"
#include "../../scene/Material/SmallNormal.h"
#include "../../scene/Material/ColorAndOpacity.h"
#include "../../scene/Material/ColorAndNormal.h"
#include "../../scene/Material/ColorAndNormalAndValue.h"
#include "../../scene/Octree/BaseTree.h"
#include "../../scene/Octree/ColorChannelMultiRootTree.h"
#include "../../scene/Octree/MultiRootBitsTree.h"
#include "../../scene/Octree/MaterialLibraryTree.h"
#include "ColorQuantizerFactory.h"
#include "NormalQuantizerFactory.h"
#include "ColorAndValueQuantizerFactory.h"
#include "CompressedTextureFactory.h"
#include "../Voxelizer/TriangleMeshVoxelizer.h"
#include "../Voxelizer/PVMVoxelizer.h"
#include "StandardOctreeBuilder.h"
#include "MultiRootOctreeBuilder.h"
#include "ColorChannelMultiRootOctreeBuilder.h"
#include "MultiBitsMultiRootOctreeBuilder.h"
#include "HierarchicalMaterialOctreeBuilder.h"
#include "UniqueIndexMaterialOctreeBuilder.h"
#include "UniqueIndexShiftColoredOctreeBuilder.h"
#include "RandomOctreeBuilder.h"
#include "MaterialLibraryMultiRootOctreeBuilder.h"
#include "../../PropertyLoader.h"
#include "../Util/Stopwatch.h"
std::string OctreeBuilder::mTreeType = "s";
OctreeBuilder::OctreeBuilder() {}
OctreeBuilder::~OctreeBuilder() {}
BaseOctreeBuilder* OctreeBuilder::mInstance = NULL;
BaseQuantizer<Color, ColorCompare>* OctreeBuilder::mColorQuantizer = NULL;
BaseQuantizer<SmallNormal, NormalCompare>* OctreeBuilder::mNormalQuantizer = NULL;
BaseQuantizer<ColorAndNormal, ColorAndNormalCompare>* OctreeBuilder::mColorAndNormalQuantizer = NULL;
BaseQuantizer<ColorAndOpacity, ColorAndOpacityCompare>* OctreeBuilder::mColorAndOpacityQuantizer = NULL;
BaseQuantizer<ColorAndNormalAndValue, ColorAndNormalAndValueCompare>* OctreeBuilder::mColorAndNormalAndValueQuantizer = NULL;
BaseOctreeBuilder* OctreeBuilder::Instance() {
return mInstance;
}
void OctreeBuilder::SetTreeType(std::string type)
{
if (mInstance != NULL && type != mTreeType)
{
Destroy();
Create(type);
}
}
std::string OctreeBuilder::GetTreeType()
{
return mTreeType;
}
void OctreeBuilder::Create()
{
// Destroy any old octree builders (to prevent memory leaks)
Destroy();
// Create the new octree builder
Create(SettingsParser::GetTreeTypeFromSettings());
}
void OctreeBuilder::Destroy()
{
if (mInstance != NULL)
delete mInstance;
mInstance = NULL;
if (mColorQuantizer != NULL)
delete mColorQuantizer;
mColorQuantizer = NULL;
if (mColorAndNormalQuantizer != NULL) delete mColorAndNormalQuantizer;
mColorAndNormalQuantizer = NULL;
}
OctreeBuilderStatistics OctreeBuilder::BuildOctree()
{
PropertyLoader::Create();
return BuildOctree(SettingsParser::GetMaxLevelFromSettings(), PropertyLoader::Instance()->GetProperty("obj_to_dag"), PropertyLoader::Instance()->GetProperty("dag_file"));
}
OctreeBuilderStatistics OctreeBuilder::BuildOctree(unsigned8 depth)
{
PropertyLoader::Create();
return BuildOctree(depth, PropertyLoader::Instance()->GetProperty("obj_to_dag"), PropertyLoader::Instance()->GetProperty("dag_file"));
}
OctreeBuilderStatistics OctreeBuilder::BuildOctree(unsigned8 depth, std::string sceneFile, std::string dagFile)
{
mInstance->SetOutputFile(dagFile);
mInstance->SetVerbose(SettingsParser::GetVerboseFromSettings());
mInstance->SetForceRebuild(SettingsParser::GetForceRebuildFromSettings());
std::string filetype = PathHelper::GetExtension(sceneFile);
StringHelper::ToUpper(filetype);
BaseVoxelizer* voxelizer;
if (filetype == "PVM" || filetype == "DAT")
voxelizer = new PVMVoxelizer();
else
voxelizer = new TriangleMeshVoxelizer();
voxelizer->Initialize();
voxelizer->LoadScene(sceneFile);
OctreeBuilderStatistics res = mInstance->BuildOctree(*voxelizer, depth, (unsigned8)PropertyLoader::Instance()->GetIntProperty("octreebuilder_max_single_pass_layers"));
voxelizer->UnloadScene();
delete voxelizer;
return res;
}
void OctreeBuilder::Create(std::string type)
{
TreeTypeDescriptor descr = TreeTypeParser::GetTreeTypeDescriptor(type);
if (descr.material == "c")
mColorQuantizer = ColorQuantizerFactory::Create(descr.quantizer);
else if (descr.material == "n")
mNormalQuantizer = NormalQuantizerFactory::Create(descr.quantizer);
else if (descr.material == "cn")
mColorAndNormalQuantizer = ColorAndNormalQuantizerFactory::Create(descr.quantizer);
else if (descr.material == "cnr")
mColorAndNormalAndValueQuantizer = ColorAndNormalAndValueQuantizerFactory::Create(descr.quantizer);
else if (descr.material == "co")
mColorAndOpacityQuantizer = ColorAndOpacityQuantizerFactory::Create(descr.quantizer);
if (descr.globalType == UNIQUEINDEX)
{
// Parse the number of levels without material information (LOD) if it isn't empty.
unsigned8 levelsWithoutMaterial = TreeTypeParser::GetLevelsWithoutMaterials(descr);
if (descr.additionalTypeInfo != "" && descr.additionalTypeInfo[0] == 's')
{
assert(descr.material == "c");
mInstance = new UniqueIndexShiftColoredOctreeBuilder(descr.textureCompressor, mColorQuantizer, levelsWithoutMaterial);
}
else
{
if (descr.material == "c")
mInstance = new UniqueIndexMaterialOctreeBuilder<Color, ColorCompare>(descr.textureCompressor, mColorQuantizer, levelsWithoutMaterial);
else if (descr.material == "n")
mInstance = new UniqueIndexMaterialOctreeBuilder<SmallNormal, NormalCompare>(descr.textureCompressor, mNormalQuantizer, levelsWithoutMaterial);
else if (descr.material == "cn")
mInstance = new UniqueIndexMaterialOctreeBuilder<ColorAndNormal, ColorAndNormalCompare>(descr.textureCompressor, mColorAndNormalQuantizer, levelsWithoutMaterial);
else if (descr.material == "cnr")
mInstance = new UniqueIndexMaterialOctreeBuilder<ColorAndNormalAndValue, ColorAndNormalAndValueCompare>(descr.textureCompressor, mColorAndNormalAndValueQuantizer, levelsWithoutMaterial);
else if (descr.material == "co")
mInstance = new UniqueIndexMaterialOctreeBuilder<ColorAndOpacity, ColorAndOpacityCompare>(descr.textureCompressor, mColorAndOpacityQuantizer, levelsWithoutMaterial);
}
}
else if (descr.globalType == HIERARCHICAL && descr.additionalTypeInfo == "")
{
if (descr.material == "c")
mInstance = new HierarchicalMaterialOctreeBuilder<Color, ColorCompare>(mColorQuantizer);
else if (descr.material == "n")
mInstance = new HierarchicalMaterialOctreeBuilder<SmallNormal, NormalCompare>(mNormalQuantizer);
else if (descr.material == "cn")
mInstance = new HierarchicalMaterialOctreeBuilder<ColorAndNormal, ColorAndNormalCompare>(mColorAndNormalQuantizer);
else if (descr.material == "cnr")
mInstance = new HierarchicalMaterialOctreeBuilder<ColorAndNormalAndValue, ColorAndNormalAndValueCompare>(mColorAndNormalAndValueQuantizer);
else if (descr.material == "co")
mInstance = new HierarchicalMaterialOctreeBuilder<ColorAndOpacity, ColorAndOpacityCompare>(mColorAndOpacityQuantizer);
}
else if (descr.globalType == MULTIROOT)
{
if (descr.additionalTypeInfo == "cc")
mInstance = new MaterialMultiRootOctreeBuilder<ColorChannel>(type);
else if (descr.additionalTypeInfo == "" || (descr.additionalTypeInfo.size() == 1 && descr.additionalTypeInfo[0] >= 49 && descr.additionalTypeInfo[0] <= 56))
{
unsigned8 bitsPerChannel = TreeTypeParser::GetBitsPerChannel(descr);
mInstance = new MultiRootOctreeBuilder(bitsPerChannel);
}
else
{
unsigned8 bitsPerChannel = TreeTypeParser::GetBitsPerChannel(descr);
unsigned8 bitsPerTree = TreeTypeParser::GetBitsPerTree(descr);
switch (bitsPerTree)
{
case 1: mInstance = new MaterialMultiRootOctreeBuilder<BitsMaterial<1>>(type, bitsPerChannel); break;
case 2: mInstance = new MaterialMultiRootOctreeBuilder<BitsMaterial<2>>(type, bitsPerChannel); break;
case 3: mInstance = new MaterialMultiRootOctreeBuilder<BitsMaterial<3>>(type, bitsPerChannel); break;
case 4: mInstance = new MaterialMultiRootOctreeBuilder<BitsMaterial<4>>(type, bitsPerChannel); break;
case 5: mInstance = new MaterialMultiRootOctreeBuilder<BitsMaterial<5>>(type, bitsPerChannel); break;
case 6: mInstance = new MaterialMultiRootOctreeBuilder<BitsMaterial<6>>(type, bitsPerChannel); break;
case 7: mInstance = new MaterialMultiRootOctreeBuilder<BitsMaterial<7>>(type, bitsPerChannel); break;
case 8: mInstance = new MaterialMultiRootOctreeBuilder<BitsMaterial<8>>(type, bitsPerChannel); break;
}
}
}
else if (descr.globalType == RANDOM)
{
mInstance = new RandomOctreeBuilder();
}
else if (descr.globalType == BITTREES)
{
if (descr.additionalTypeInfo == "l" && descr.material == "c")
mInstance = new MaterialLibraryMultiRootOctreeBuilder(mColorQuantizer);
}
else
{
mInstance = new StandardOctreeBuilder();
}
mTreeType = type;
}

View File

@@ -0,0 +1,46 @@
#pragma once
#include "../Defines.h"
#include "OctreeBuilderStatistics.h"
#include "BaseOctreeBuilder.h"
#include "../../scene/Material/MaterialQuantizer/ColorAndValueQuantizer.h"
//#include "../../scene/Material/MaterialQuantizer/BaseQuantizer.h"
//#include "../../scene/Material/SmallNormal.h"
class Root;
class BaseColorQuantizer;
class SmallNormal;
struct NormalCompare;
class TriangleMeshVoxelizer;
class PVMVoxelizer;
// Singleton wrapper that reads the settings and creates the correct octreebuilder
class OctreeBuilder
{
friend BaseOctreeBuilder;
public:
static void Create();
static void SetTreeType(std::string type);
static std::string GetTreeType();
static void Destroy();
static OctreeBuilderStatistics BuildOctree();
static OctreeBuilderStatistics BuildOctree(unsigned8 depth);
static OctreeBuilderStatistics BuildOctree(unsigned8 depth, std::string sceneFile, std::string dagFile);
static BaseOctreeBuilder* Instance();
private:
static BaseOctreeBuilder* mInstance;
static BaseQuantizer<Color, ColorCompare>* mColorQuantizer;
static BaseQuantizer<SmallNormal, NormalCompare>* mNormalQuantizer;
static BaseQuantizer<ColorAndNormal, ColorAndNormalCompare>* mColorAndNormalQuantizer;
static BaseQuantizer<ColorAndOpacity, ColorAndOpacityCompare>* mColorAndOpacityQuantizer;
static BaseQuantizer<ColorAndNormalAndValue, ColorAndNormalAndValueCompare>* mColorAndNormalAndValueQuantizer;
static void Create(std::string type);
static std::string mTreeType;
OctreeBuilder();
~OctreeBuilder();
};

View File

@@ -0,0 +1,73 @@
#pragma once
#include <vector>
#include <string>
#include "../Defines.h"
struct OctreeBuilderStatistics
{
public:
unsigned8 levels;
std::string type;
double validCoordBuildtime;
double depthPeelingTime;
double finalizationTime;
double totalTime;
std::vector<size_t> octreeNodesPerLevel;
std::vector<size_t> dagNodesPerLevel;
OctreeBuilderStatistics(unsigned8 levels)
{
this->levels = levels;
validCoordBuildtime = depthPeelingTime = finalizationTime = totalTime = 0;
octreeNodesPerLevel = std::vector<size_t>(levels + 1);
dagNodesPerLevel = std::vector<size_t>(levels + 1);
}
size_t GetOctreeNodeCount() const
{
size_t octreeNodeCount = 0;
for (unsigned8 level = 0; level <= levels; level++)
octreeNodeCount += octreeNodesPerLevel[level];
return octreeNodeCount;
}
size_t GetDAGNodeCount() const
{
size_t dagNodeCount = 0;
for (unsigned8 level = 0; level <= levels; level++)
dagNodeCount += dagNodesPerLevel[level];
return dagNodeCount;
}
long double GetCompression() const
{
return (long double)GetOctreeNodeCount() / (long double)GetDAGNodeCount();
}
long double GetCompression(unsigned8 level) const
{
return (long double)octreeNodesPerLevel[level] / (long double)dagNodesPerLevel[level];
}
void Print() const
{
printf("DAG created with the following properties:\n");
printf("Total time : %10u ms\n", (unsigned)(totalTime * 1000));
printf("Valid subtree calculation time : %10u ms\n", (unsigned)(validCoordBuildtime * 1000));
printf("Depth peeling time : %10u ms\n", (unsigned)(depthPeelingTime * 1000));
printf("Subtree finalization time : %10u ms\n", (unsigned)(finalizationTime * 1000));
printf("Total nodes : %10zu\n", GetOctreeNodeCount());
printf("DAG nodes : %10zu\n", GetDAGNodeCount());
printf("Compression : %10.2Lf\n", GetCompression());
printf("\n");
printf("Statistics per level:\n");
printf("Level Octree (#) DAG (#) Compression\n");
for (unsigned8 level = 0; level <= levels; level++)
printf("%5d %12zu %12zu %12.2Lf\n", level, octreeNodesPerLevel[level], dagNodesPerLevel[level], GetCompression(level));
}
};

View File

@@ -0,0 +1,476 @@
#include "OctreeConverter.h"
#include "OctreeLoader.h"
#include "SettingsParser.h"
#include "TreeTypeParser.h"
#include "ColorQuantizerFactory.h"
#include "CompressedTextureFactory.h"
#include "../Util/Stopwatch.h"
#include "../../scene/Material/MaterialQuantizer/ColorQuantizer/BaseColorQuantizer.h"
#include "../../PropertyLoader.h"
#include <regex>
#include "../../scene/Octree/BaseTree.h"
#include "../../scene/Octree/Tree.h"
#include "../../scene/Octree/MaterialLibraryTree.h"
#include "../../scene/Octree/HierarchicalShiftingColoredTree.h"
#include "../../scene/Octree/HierarchicalColorsOnlyTree.h"
#include "../../scene/Octree/MaterialLibraryUniqueIndexTree.h"
#ifdef _WIN32
#include <Windows.h>
#endif
bool OctreeConverter::Convert()
{
PropertyLoader::Create();
auto propertyLoader = PropertyLoader::Instance();
if (!propertyLoader->GetBoolProperty("octreebuilder_tryconvert") || !propertyLoader->GetBoolProperty("octreebuilder_usecache"))
return false;
bool verbose = propertyLoader->GetProperty("octreebuilder_verbose") != "0";
if (verbose) printf("Trying to convert an existing tree to the wanted treetype.\n");
std::string octreeType = propertyLoader->GetProperty("octree_type");
unsigned8 maxLevel = propertyLoader->GetIntProperty("shader_max_level");
std::string filename = propertyLoader->GetProperty("dag_file");
bool res = ConvertTo(octreeType, maxLevel, filename, verbose);
if (verbose)
{
if (res) printf("Conversion succeeded\n");
if (!res) printf("No valid conversion found\n");
}
return res;
}
bool OctreeConverter::ConvertTo(std::string destinationType, unsigned8 destinationDepth, std::string dagFileName, bool verbose)
{
#ifdef _WIN32
// Go through all .oct files that can support the given dag file.
// For each of the files found, try conversion.
std::string dagStrippedFilename = dagFileName;
const size_t last_slash_idx = dagStrippedFilename.find_last_of("\\/");
if (std::string::npos != last_slash_idx)
{
dagStrippedFilename.erase(0, last_slash_idx + 1);
}
std::string validFileWildcard = std::string(dagFileName + "*.oct");
std::regex fileNameMatcher(dagStrippedFilename + "_([0-9]+)_(.+).oct");
std::smatch sm;
WIN32_FIND_DATA FindFileData;
HANDLE hFind = FindFirstFile(validFileWildcard.c_str(), &FindFileData);
LARGE_INTEGER filesize;
// Find all convertable files
std::vector<FileInfo> convertableFiles;
while (hFind != INVALID_HANDLE_VALUE)
{
// Try conversion
std::string foundFilename(FindFileData.cFileName);
filesize.LowPart = FindFileData.nFileSizeLow;
filesize.HighPart = FindFileData.nFileSizeHigh;
// Extract the level and type from the filename
if (std::regex_match(foundFilename, sm, fileNameMatcher))
{
unsigned8 sourceDepth = std::stoi(sm.str(1));
std::string sourceType = sm.str(2);
if (CanConvert(sourceType, destinationType, sourceDepth, destinationDepth))
convertableFiles.push_back(FileInfo(foundFilename, sourceType, sourceDepth, filesize.QuadPart));
}
if (!FindNextFile(hFind, &FindFileData))
{
FindClose(hFind);
hFind = INVALID_HANDLE_VALUE;
}
}
// Sort them on filesize, assuming that smaller files are always quicker to convert
std::sort(convertableFiles.begin(), convertableFiles.end(), [&](const FileInfo& a, const FileInfo& b)
{
return a.filesize < b.filesize;
});
for (const FileInfo& info : convertableFiles)
{
if (Convert(info.treeType, destinationType, info.depth, destinationDepth, dagFileName, verbose))
return true;
}
#endif
return false;
}
// Check if a certain conversion is valid (theore
bool OctreeConverter::CanConvert(std::string sourceType, std::string destinationType, unsigned8 sourceDepth, unsigned8 destinationDepth)
{
// Converting to the same type always works
if (sourceType == destinationType && sourceDepth == destinationDepth)
return true;
if (sourceDepth != destinationDepth)
return false; // Can't change the depth...
TreeTypeDescriptor destDescr = TreeTypeParser::GetTreeTypeDescriptor(destinationType);
TreeTypeDescriptor sourceDescr = TreeTypeParser::GetTreeTypeDescriptor(sourceType);
std::string normalizedSourceQuantizerType = ColorQuantizerFactory::GetNormalizedType(sourceDescr.quantizer);
std::string normalizedDestinationQuantizerType = ColorQuantizerFactory::GetNormalizedType(destDescr.quantizer);
// Any tree type can be converted to standard if the source depth is at least as deep as the destination depth
if (destDescr.globalType == STANDARD) return true;
else if (destDescr.globalType == HIERARCHICAL)
{
return sourceDepth == destinationDepth
&& sourceDescr.globalType == HIERARCHICAL
&& sourceDescr.additionalTypeInfo == "" && (destDescr.additionalTypeInfo == "" || destDescr.additionalTypeInfo == "s")
&& destDescr.material == sourceDescr.material
&& (normalizedSourceQuantizerType == "" || normalizedSourceQuantizerType == normalizedDestinationQuantizerType);
}
else if (destDescr.globalType == UNIQUEINDEX)
{
return sourceDepth == destinationDepth
&& sourceDescr.globalType == UNIQUEINDEX && sourceDescr.material == "c"
&& destDescr.material == "c"
&& (normalizedSourceQuantizerType == "" || normalizedSourceQuantizerType == normalizedDestinationQuantizerType)
&& sourceDescr.additionalTypeInfo == "" && destDescr.additionalTypeInfo == "";
}
else if (destDescr.globalType == ONLYMATERIAL)
{
return sourceDepth == destinationDepth
&& destDescr.material == "c" && sourceDescr.material == "c"
&& sourceDescr.globalType == HIERARCHICAL
&& (normalizedSourceQuantizerType == "" || normalizedSourceQuantizerType == normalizedDestinationQuantizerType);
}
return false;
}
bool OctreeConverter::Convert(std::string sourceType, std::string destinationType, unsigned8 sourceDepth, unsigned8 destinationDepth, std::string dagFileName, bool verbose)
{
if (!CanConvert(sourceType, destinationType, sourceDepth, destinationDepth)) return false;
TreeTypeDescriptor destDescr = TreeTypeParser::GetTreeTypeDescriptor(destinationType);
switch (destDescr.globalType)
{
case HIERARCHICAL:
if (destDescr.material == "c")
{
if (destDescr.additionalTypeInfo == "s")
return ConvertToHierarchicalColorShift(sourceType, destinationType, sourceDepth, destinationDepth, dagFileName, verbose);
else
return ConvertToHierarchicalColored(sourceType, destinationType, sourceDepth, destinationDepth, dagFileName, verbose);
}
break;
case UNIQUEINDEX: return ConvertToUniqueIndex(sourceType, destinationType, sourceDepth, destinationDepth, dagFileName, verbose);
case STANDARD: return ConvertToStandard(sourceType, sourceDepth, destinationDepth, dagFileName, verbose);
case ONLYMATERIAL: return ConvertToOnlyMaterials(sourceType, destinationType, sourceDepth, destinationDepth, dagFileName, verbose);
}
return false;
}
bool OctreeConverter::ConvertToStandard(std::string sourceType, unsigned8 sourceDepth, unsigned8 destinationDepth, std::string dagFileName, bool verbose)
{
if (verbose) printf("Found valid octree file: %s, converting...\n", OctreeLoader::GetFullFilename(sourceType, sourceDepth, dagFileName).c_str());
BaseTree* originalTree = OctreeLoader::ReadCache(sourceType, sourceDepth, dagFileName);
if (originalTree == NULL) return false;
Tree<>* standardTree = (Tree<>*)OctreeLoader::CreateTree("s", destinationDepth);
originalTree->Shave(destinationDepth);
standardTree->MoveShallow(originalTree);
delete originalTree;
standardTree->ToDAG();
OctreeLoader::WriteCache(standardTree, "s", dagFileName, verbose);
delete standardTree;
return true;
}
static void CompressHierarchicalTreeColors(MaterialLibraryTree<Color, ColorCompare>* tree, std::string compressor)
{
std::vector<Color> leafMaterials = tree->GetLeafMaterials();
tbb::parallel_sort(leafMaterials.begin(), leafMaterials.end(), ColorCompare());
leafMaterials.erase(std::unique(leafMaterials.begin(), leafMaterials.end()), leafMaterials.end());
std::vector<glm::u8vec3> leafColors(leafMaterials.size());
tbb::parallel_for(size_t(0), leafMaterials.size(), [&](size_t i)
{
leafColors[i] = leafMaterials[i].GetColor();
});
tbb::parallel_sort(leafColors.begin(), leafColors.end(), u8vec3comparer());
leafColors.erase(std::unique(leafColors.begin(), leafColors.end()), leafColors.end());
auto colorQuantizer = ColorQuantizerFactory::Create(compressor);
auto colorReplacers = colorQuantizer->QuantizeColors(leafColors);
std::map<Color, Color, ColorCompare> materialReplacers;
for (auto colorReplacer = colorReplacers->begin(); colorReplacer != colorReplacers->end(); std::advance(colorReplacer, 1))
materialReplacers.insert(std::make_pair(Color(colorReplacer->first), Color(colorReplacer->second)));
delete colorReplacers;
delete colorQuantizer;
tree->ReplaceLeafMaterials(materialReplacers);
}
bool OctreeConverter::ConvertToHierarchicalColored(std::string sourceType, std::string destinationType, unsigned8 sourceDepth, unsigned8 destinationDepth, std::string dagFileName, bool verbose)
{
// Only works if trees are of the same depth. Higher depth will mean the colors are averaged which might lead to wrong results
if (sourceDepth != destinationDepth)
return false;
TreeTypeDescriptor sourceDescr = TreeTypeParser::GetTreeTypeDescriptor(sourceType);
TreeTypeDescriptor destDescr = TreeTypeParser::GetTreeTypeDescriptor(destinationType);
// Make sure that the destination type is actually what is expected
if (destDescr.globalType != HIERARCHICAL || destDescr.material != "c" || destDescr.additionalTypeInfo != "")
return false;
// Only colored and hierarchical trees can be converted, so they need to match this regex
if (sourceDescr.globalType != HIERARCHICAL || sourceDescr.additionalTypeInfo != "" || sourceDescr.material != "c")
return false;
std::string normalizedSourceQuantizerType = ColorQuantizerFactory::GetNormalizedType(sourceDescr.quantizer);
std::string normalizedDestinationQuantizerType = ColorQuantizerFactory::GetNormalizedType(destDescr.quantizer);
// Only trees with full colors or the same compression scheme as the destination type can be compressed
if (normalizedSourceQuantizerType != "" && normalizedSourceQuantizerType != normalizedDestinationQuantizerType)
return false;
// Now there are 4 options:
// Source is hierarchical fully colored
// Source is not-hierarchical fully colored
// Source is hierarchical compressed colored
// Source is not-hierarchical compressed colored
if (sourceDescr.globalType == HIERARCHICAL)
{
// Apparently we already have the desired type, so just return true
if (normalizedDestinationQuantizerType == normalizedSourceQuantizerType)
return true;
// Convertert fully colored hierarchical root to compressed colored hierarchical root
if (verbose) printf("Converting fully colored tree in %s to compressed colored tree...\n", OctreeLoader::GetFullFilename(sourceType, sourceDepth, dagFileName).c_str());
MaterialLibraryTree<Color, ColorCompare>* source = (MaterialLibraryTree<Color, ColorCompare>*)OctreeLoader::ReadCache(sourceType, sourceDepth, dagFileName);
if (source == NULL)
{
if (verbose) printf("Reading the source tree failed...\n");
return false;
}
if (verbose) printf("Quantizing original materials...\n");
CompressHierarchicalTreeColors(source, normalizedDestinationQuantizerType);
if (verbose) printf("Clearing propagation...\n");
source->ClearPropagation();
if (verbose) printf("Recalculating DAG (since the materials are now compressed).\n");
source->ToDAG();
if (verbose) printf("Propagating materials...\n");
source->PropagateMaterials();
OctreeLoader::WriteCache(source, destinationType, dagFileName, verbose);
delete source;
return true;
}
return false;
}
bool OctreeConverter::ConvertToUniqueIndex(std::string sourceType, std::string destinationType, unsigned8 sourceDepth, unsigned8 destinationDepth, std::string dagFileName, bool verbose)
{
// Conversion currently only allowed from other UniqueIndexRoots
if (sourceDepth != destinationDepth) return false;
TreeTypeDescriptor sourceDescr = TreeTypeParser::GetTreeTypeDescriptor(sourceType);
TreeTypeDescriptor destDescr = TreeTypeParser::GetTreeTypeDescriptor(destinationType);
std::string normalizedSourceQuantizerType = ColorQuantizerFactory::GetNormalizedType(sourceDescr.quantizer);
std::string normalizedDestinationQuantizerType = ColorQuantizerFactory::GetNormalizedType(destDescr.quantizer);
// Check the source and destination type to be valid
if (destDescr.globalType != UNIQUEINDEX || destDescr.material != "c")
return false;
if ((/*sourceDescr.globalType != HIERARCHICAL && sourceDescr.globalType != COLORED && */sourceDescr.globalType != UNIQUEINDEX) || sourceDescr.material != "c")
return false;
// Only trees with full colors or the same compression scheme as the destination type can be compressed
if (normalizedSourceQuantizerType != "" && normalizedSourceQuantizerType != normalizedDestinationQuantizerType)
return false;
if (sourceDescr.additionalTypeInfo != "" || destDescr.additionalTypeInfo != "")
return false;
if (sourceDescr.globalType == UNIQUEINDEX)
{
// Check if the current type is not already the desired type
if (sourceDescr.textureCompressor == destDescr.quantizer && normalizedDestinationQuantizerType == normalizedSourceQuantizerType) return true;
// If not, load the source tree
if (verbose) printf("Reading tree in %s...\n", OctreeLoader::GetFullFilename(sourceType, sourceDepth, dagFileName).c_str());
MaterialLibraryUniqueIndexTree<Color, ColorCompare>* source = (MaterialLibraryUniqueIndexTree<Color, ColorCompare>*)OctreeLoader::ReadCache(sourceType, sourceDepth, dagFileName);
if (source == NULL)
{
if (verbose) printf("Reading the source tree failed...\n");
return false;
}
if (normalizedSourceQuantizerType != normalizedDestinationQuantizerType)
{
// Quantize all materials
if (verbose) printf("Quantizing materials...");
Stopwatch watch; watch.Reset();
std::vector<Color> materials = source->GetUniqueMaterials();
BaseColorQuantizer* colorQuantizer = ColorQuantizerFactory::Create(normalizedDestinationQuantizerType);
std::map<Color, Color, ColorCompare>* colorReplacers = colorQuantizer->QuantizeMaterials(materials);
delete colorQuantizer;
std::unordered_map<Color, Color> colorReplacersUnorderedMap;
for (auto colorReplacer : *colorReplacers) colorReplacersUnorderedMap.insert(colorReplacer);
delete colorReplacers;
if (verbose) printf("Materials quantized in %u ms.\n Replacing materials...", (unsigned)(watch.GetTime() * 1000.0));
watch.Reset();
source->ReplaceMaterials(colorReplacersUnorderedMap);
if (verbose) printf("Materials replaced in %u ms.\n", (unsigned)(watch.GetTime() * 1000.0));
}
if (sourceDescr.textureCompressor != destDescr.textureCompressor)
{
// Replace the compressed texture type
if (verbose) printf("Replacing texture compressor...");
Stopwatch watch; watch.Reset();
source->ReplaceCompressedTexture(CompressedTextureFactory<MaterialLibraryPointer>::GetCompressedTexture(destDescr.textureCompressor));
if (verbose) printf("Texture compressor replaced in %u ms.\n", (unsigned)(watch.GetTime() * 1000.0));
}
else
{
if (verbose) printf("Recompressing texture with quantized materials...");
Stopwatch watch; watch.Reset();
source->Recompress();
if (verbose) printf("Done in %u ms.\n", (unsigned)(watch.GetTime() * 1000.0));
}
OctreeLoader::WriteCache(source, destinationType, dagFileName, verbose);
delete source;
return true;
}
return false;
}
bool OctreeConverter::ConvertToHierarchicalColorShift(std::string sourceType, std::string destinationType, unsigned8 sourceDepth, unsigned8 destinationDepth, std::string dagFileName, bool verbose)
{
if (sourceDepth != destinationDepth)
return false;
TreeTypeDescriptor sourceDescr = TreeTypeParser::GetTreeTypeDescriptor(sourceType);
TreeTypeDescriptor destDescr = TreeTypeParser::GetTreeTypeDescriptor(destinationType);
// Make sure the source and destination type is valid
assert(destDescr.globalType == HIERARCHICAL && destDescr.material == "c" && destDescr.additionalTypeInfo == "s");
assert(sourceDescr.globalType == HIERARCHICAL && sourceDescr.material == "c");
std::string normalizedSourceQuantizerType = ColorQuantizerFactory::GetNormalizedType(sourceDescr.quantizer);
std::string normalizedDestinationQuantizerType = ColorQuantizerFactory::GetNormalizedType(destDescr.quantizer);
// Only trees with full colors or the same compression scheme as the destination type can be compressed
if (normalizedSourceQuantizerType != "" && normalizedSourceQuantizerType != normalizedDestinationQuantizerType)
return false;
// Remove the second characted, as that is the one that indicates that we want a shifting tree
std::string hierarchicalColoredDestinationType = std::string(destinationType).erase(1, 1);
// If we're dealing with a normal "colored octree" that isn't hierarchical, or has a different compression, convert it to hierarchical first:
if (TreeTypeParser::GetGlobalType(sourceType) != HIERARCHICAL || normalizedDestinationQuantizerType != normalizedSourceQuantizerType)
{
if (verbose) printf("Checking cache for hierarchical tree with correct compression...");
if (OctreeLoader::VerifyCache(hierarchicalColoredDestinationType, sourceDepth, dagFileName))
{
if (verbose) printf("Cache file found.\n");
}
else
{
if (verbose) printf("Nothing found.\nConverting non-hierarchical tree %s to hierarchical tree with correct compression.\n", OctreeLoader::GetFullFilename(sourceType, sourceDepth, dagFileName).c_str());
if (OctreeConverter::ConvertToHierarchicalColored(sourceType, hierarchicalColoredDestinationType, sourceDepth, destinationDepth, dagFileName, verbose))
return false;
}
}
// By now we're sure that a fully colored or compressed colored hierarchical octree with the same compression exists
// Let's convert it to a shifter:
if (verbose) printf("Reading source tree to new shifting tree...");
auto source = (MaterialLibraryTree<Color, ColorCompare>*)OctreeLoader::ReadCache(hierarchicalColoredDestinationType, destinationDepth, dagFileName);
auto dest = (HierarchicalShiftingColoredTree*)OctreeLoader::CreateTree(destinationType, destinationDepth);
std::vector<Color> sourceMaterials = source->GetMaterials();
dest->MoveShallow(source);
delete source;
dest->SetMaterials(sourceMaterials);
if (verbose) printf("\nReplacing original colors by color shifts...\n");
dest->ReplaceColorsByShifts();
if (verbose) printf("Converting the tree containing color shifts to a DAG...\n");
dest->ToDAG();
OctreeLoader::WriteCache(dest, destinationType, dagFileName, verbose);
delete dest;
if (verbose) printf("Conversion succeeded");
return true;
}
bool OctreeConverter::ConvertToOnlyMaterials(std::string sourceType, std::string destinationType, unsigned8 sourceDepth, unsigned8 destinationDepth, std::string dagFileName, bool verbose)
{
if (sourceDepth != destinationDepth)
return false;
TreeTypeDescriptor destDescr = TreeTypeParser::GetTreeTypeDescriptor(destinationType);
if (destDescr.globalType != ONLYMATERIAL)
return false;
if (destDescr.material == "c")
return ConvertToOnlyColors(sourceType, destinationType, destinationDepth, dagFileName, verbose);
// No valid type found
return false;
}
bool OctreeConverter::ConvertToOnlyColors(std::string sourceType, std::string destinationType, unsigned8 destinationDepth, std::string dagFileName, bool verbose)
{
TreeTypeDescriptor destDescr = TreeTypeParser::GetTreeTypeDescriptor(destinationType);
TreeTypeDescriptor sourceDescr = TreeTypeParser::GetTreeTypeDescriptor(sourceType);
// Make sure that the destination type is actually what is expected
if (destDescr.globalType != ONLYMATERIAL || destDescr.material != "c") // Make sure the destination is actual the type we want
return false;
// Only colored and hierarchical trees can be converted to only color trees
if (sourceDescr.globalType != HIERARCHICAL || sourceDescr.material != "c")
return false;
std::string normalizedSourceQuantizerType = ColorQuantizerFactory::GetNormalizedType(sourceDescr.quantizer);
std::string normalizedDestinationQuantizerType = ColorQuantizerFactory::GetNormalizedType(destDescr.quantizer);
// Only trees with full colors or the same compression scheme as the destination type can be compressed
if (normalizedSourceQuantizerType != "" && normalizedSourceQuantizerType != normalizedDestinationQuantizerType)
return false;
// Remove the second characted, as that is the one that indicates that we want a shifting tree
std::string hierarchicalColoredDestinationType = "h" + std::string(destinationType).erase(0, 1);
// If we're dealing with a normal "colored octree" that isn't hierarchical, or has a different compression, convert it to hierarchical first:
if (TreeTypeParser::GetGlobalType(sourceType) != HIERARCHICAL || normalizedDestinationQuantizerType != normalizedSourceQuantizerType)
{
if (verbose) printf("Checking cache for hierarchical tree with correct compression...");
if (OctreeLoader::VerifyCache(hierarchicalColoredDestinationType, destinationDepth, dagFileName))
{
if (verbose) printf("Cache file found.\n");
}
else
{
if (verbose) printf("Nothing found.\nConverting non-hierarchical tree %s to hierarchical tree with correct compression.\n", OctreeLoader::GetFullFilename(sourceType, destinationDepth, dagFileName).c_str());
if (OctreeConverter::ConvertToHierarchicalColored(sourceType, hierarchicalColoredDestinationType, destinationDepth, destinationDepth, dagFileName, verbose))
return false;
}
}
// By now we're sure that a fully colored or compressed colored hierarchical octree with the same compression exists
// Let's convert it to a tree with only colors:
if (verbose) printf("Reading source tree and moving to new tree with colors only...");
auto source = (MaterialLibraryTree<Color, ColorCompare>*)OctreeLoader::ReadCache(hierarchicalColoredDestinationType, destinationDepth, dagFileName);
auto dest = (HierarchicalColorsOnlyTree*)OctreeLoader::CreateTree(destinationType, destinationDepth);
std::vector<Color> sourceMaterials = source->GetMaterials();
dest->MoveShallow(source);
delete source;
dest->SetMaterials(sourceMaterials);
if (verbose) printf("\nConverting to DAG while merging empty nodes...\n");
auto quantizer = ColorQuantizerFactory::Create(normalizedDestinationQuantizerType);
dest->ToDAG(quantizer);
OctreeLoader::WriteCache(dest, destinationType, dagFileName, verbose);
delete dest;
if (verbose) printf("Conversion succeeded");
return true;
}

View File

@@ -0,0 +1,36 @@
#pragma once
#include <string>
#include "../Defines.h"
class OctreeConverter
{
public:
// Calls ConvertTo for the required tree type based on the settings
static bool Convert();
// Given some destination type, tries to find some cache file that can be converted
static bool ConvertTo(std::string destinationType, unsigned8 destinationDepth, std::string dagFileName, bool verbose = false);
// Given a source and destination type, converts one to the other and stores the converted tree. Returns true if conversion succeeded
static bool Convert(std::string sourceType, std::string destinationType, unsigned8 sourceDepth, unsigned8 destinationDepth, std::string dagFileName, bool verbose = false);
static bool CanConvert(std::string sourceType, std::string destinationType, unsigned8 sourceDepth, unsigned8 destinationDept);
private:
static bool ConvertToStandard(std::string sourceType, unsigned8 sourceDepth, unsigned8 destinationDepth, std::string dagFileName, bool verbose = false);
static bool ConvertToHierarchicalColored(std::string sourceType, std::string destinationType, unsigned8 sourceDepth, unsigned8 destinationDepth, std::string dagFileName, bool verbose = false);
static bool ConvertToHierarchicalColorShift(std::string sourceType, std::string destinationType, unsigned8 sourceDepth, unsigned8 destinationDepth, std::string dagFileName, bool verbose = false);
static bool ConvertToUniqueIndex(std::string sourceType, std::string destinationType, unsigned8 sourceDepth, unsigned8 destinationDepth, std::string dagFileName, bool verbose = false);
static bool ConvertToOnlyMaterials(std::string sourceType, std::string destinationType, unsigned8 sourceDepth, unsigned8 destinationDepth, std::string dagFileName, bool verbose = false);
static bool ConvertToOnlyColors(std::string sourceType, std::string destinationType, unsigned8 destinationDepth, std::string dagFilename, bool verbose = false);
struct FileInfo{
std::string filename;
unsigned64 filesize;
std::string treeType;
unsigned8 depth;
FileInfo(std::string filename, std::string treetype, unsigned8 depth, unsigned64 filesize) : filename(filename), filesize(filesize), treeType(treetype), depth(depth) { }
};
};

View File

@@ -0,0 +1,782 @@
#include "OctreeLoader.h"
#include "TreeTypeParser.h"
#include "SettingsParser.h"
#include "../../scene/Material/Color.h"
#include "../../scene/Material/SmallNormal.h"
#include "../../scene/Material/ColorAndNormal.h"
#include "../../scene/Material/ColorAndNormalAndValue.h"
#include "../../scene/Material/ColorAndOpacity.h"
#include "../../scene/Octree/BaseTree.h"
#include "../../scene/Octree/Tree.h"
#include "../../scene/Octree/MaterialTree.h"
#include "../../scene/Octree/MultiRootTree.h"
#include "../../scene/Octree/ColorChannelMultiRootTree.h"
#include "../../scene/Octree/MultiRootBitsTree.h"
#include "../../scene/Octree/MaterialLibraryTree.h"
#include "../../scene/Octree/HierarchicalShiftingColoredTree.h"
#include "../../scene/Octree/HierarchicalColorsOnlyTree.h"
#include "../../scene/Octree/MaterialLibraryUniqueIndexTree.h"
#include "../../scene/Octree/UniqueIndexShiftTree.h"
#include "../../scene/Octree/MaterialLibraryMultiRootTree.h"
#include "../../scene/Octree/IMaterialTexture.h"
#include "../../scene/Octree/IBlockTexture.h"
#include "../../scene/PoolBuilder/StandardPoolBuilder.h"
#include "CompressedTextureFactory.h"
#include "PoolBuilderFactory.h"
#include "../../scene/Material/MaterialLibraryPointer.h"
#include "../../scene/Material/SignedIntMaterial.h"
#include "ColorQuantizerFactory.h"
#include "../../PropertyLoader.h"
#include "../Util/Stopwatch.h"
#include "../StringHelper.h"
#include "../MathHelper.h"
bool OctreeLoader::VerifyCache()
{
bool useCache = SettingsParser::GetUseCacheFromSettings();
if (!useCache)
return false;
bool verbose = SettingsParser::GetVerboseFromSettings();
if (verbose) printf("Verifying cache... ");
Stopwatch watch; watch.Reset();
auto octreeType = SettingsParser::GetTreeTypeFromSettings();
unsigned8 maxLevel = SettingsParser::GetMaxLevelFromSettings();
std::string filename = SettingsParser::GetFilenameFromSettings();
bool cacheValid = VerifyCache(octreeType, maxLevel, filename);
if (verbose) printf("Cache is %s, confirmed in %d ms\n", cacheValid ? "valid" : "invalid", (int)(watch.GetTime() * 1000));
return cacheValid;
}
bool OctreeLoader::VerifyCache(std::string treeType, unsigned8 maxLevel, std::string filename)
{
std::string outputFile = GetFullFilename(treeType, maxLevel, filename);
auto tree = CreateTree(treeType, maxLevel);
bool cacheValid = tree->VerifyTree(outputFile.c_str());
delete tree;
return cacheValid;
}
BaseTree* OctreeLoader::ReadCache()
{
bool verbose = SettingsParser::GetVerboseFromSettings();
if (verbose) printf("Reading cache... ");
Stopwatch watch; watch.Reset();
auto octreeType = SettingsParser::GetTreeTypeFromSettings();
unsigned8 maxLevel = SettingsParser::GetMaxLevelFromSettings();
std::string filename = SettingsParser::GetFilenameFromSettings();
auto tree = ReadCache(octreeType, maxLevel, filename);
if (verbose) printf("Read tree with %llu nodes succesfully in %u ms\n", (unsigned64)tree->GetNodeCount(), (unsigned)(watch.GetTime() * 1000));
return tree;
}
BaseTree* OctreeLoader::ReadCache(std::string treeType, unsigned8 maxLevel, std::string filename, bool verbose)
{
Stopwatch watch;
watch.Reset();
std::string outputFile = GetFullFilename(treeType, maxLevel, filename);
if (verbose) printf("Reading file %s.oct.", outputFile.c_str());
auto tree = CreateTree(treeType, maxLevel);
bool readSuccessful = tree->ReadTree(outputFile.c_str());
if (!readSuccessful)
{
delete tree;
if (verbose) printf("Reading .oct file failed.\n");
return NULL;
}
if (verbose) printf("Read .oct file in %u ms.\n", (unsigned)(watch.GetTime() * 1000));
if (verbose) tree->PrintDebugInfo();
return tree;
}
void OctreeLoader::DeleteCache(std::string treeType, unsigned8 maxLevel, std::string filename)
{
try
{
std::remove(Tree<>::GetOctreeFileName(GetFullFilename(treeType, maxLevel, filename).c_str()).c_str());
}
catch (...)
{
printf("Deleting cache file %s failed", GetFullFilename(treeType.c_str(), maxLevel, filename).c_str());
}
}
bool OctreeLoader::WriteCache(BaseTree* tree, std::string treeType, std::string filename, bool verbose)
{
std::string outputFile = GetFullFilename(treeType, tree->GetMaxLevel(), filename);
// Write the final tree to a file
Stopwatch watch; watch.Reset();
if (verbose) printf("Writing DAG to \"%s\"... ", outputFile.c_str());
bool res = tree->WriteTree(outputFile.c_str());
if (verbose) printf("Writing took %d ms\n", (int)(watch.GetTime() * 1000));
return res;
}
bool OctreeLoader::VerifyPool()
{
bool useCache = SettingsParser::GetUsePoolCacheFromSettings();
if (!useCache)
return false;
std::string filename = SettingsParser::GetFilenameFromSettings();
unsigned8 maxLevel = SettingsParser::GetMaxLevelFromSettings();
std::string treeType = SettingsParser::GetTreeTypeFromSettings();
return VerifyPool(treeType, maxLevel, filename);
}
bool OctreeLoader::VerifyPool(std::string treeType, unsigned8 maxLevel, std::string filename)
{
auto fullFileName = GetFullFilename(treeType, maxLevel, filename);
StandardPoolBuilder builder;
return builder.VerifyCachedPool(fullFileName, maxLevel);
}
bool OctreeLoader::BuildNodePool(BaseTree* tree, std::string poolType, std::string poolFullFilename, std::vector<unsigned8>& outPool, unsigned& outPoolSize, bool verbose)
{
Stopwatch watch;
if (verbose) printf("Building node pool (%s)...", PoolBuilderFactory::GetReadableName(poolType).c_str());
BasePoolBuilder<BaseTree>* builder = PoolBuilderFactory::Create(poolType);
watch.Reset();
builder->BuildPool(tree, outPool);
outPoolSize = (unsigned32)MathHelper::DivideRoundUp(outPool.size(), TEXTURESIZE * TEXTURESIZE);
// Try and write the nodepool
builder->WritePool(poolFullFilename, outPool);
delete builder;
tree->WriteAdditionalPool(poolFullFilename.c_str());
//if (outPoolSize < 16) outPoolSize = 16;
outPool.resize(TEXTURESIZE * TEXTURESIZE * outPoolSize);
if (verbose) printf("Nodepool of size %u generated in %u ms.\n", outPoolSize, (unsigned)(watch.GetTime() * 1000));
return true;
}
bool OctreeLoader::ReadNodePool(BaseTree* tree, std::string poolType, std::string poolFileName, std::vector<unsigned8>& outPool, unsigned& outPoolSize, bool verbose)
{
Stopwatch watch;
watch.Reset();
BasePoolBuilder<BaseTree>* builder = PoolBuilderFactory::Create(poolType);
if (verbose) printf("Reading node pool (%s) directly... ", PoolBuilderFactory::GetReadableName(poolType).c_str());
bool success = builder->ReadPool(poolFileName, outPool);
if (success)
{
// if reading succeeded, return the
outPoolSize = (unsigned32)MathHelper::DivideRoundUp(outPool.size(), TEXTURESIZE * TEXTURESIZE);
//if (outPoolSize < 16) outPoolSize = 16;
outPool.resize(TEXTURESIZE * TEXTURESIZE * outPoolSize);
tree->ReadAdditionalPool(poolFileName.c_str());
if (verbose) printf("Reading node pool succeeded in %u ms.\n", (unsigned)(watch.GetTime() * 1000));
} else
if (verbose) printf("Reading directly failed.\n");
delete builder;
return success;
}
bool OctreeLoader::HasMaterialTexture(BaseTree* tree)
{
// If the tree can be cast to an IMaterialTexture interface, it has a material texture
return dynamic_cast<IMaterialTexture*>(tree) != NULL;
}
bool OctreeLoader::GetMaterialTexture(BaseTree* tree, std::string treeType, std::vector<unsigned char>& outMaterialTexture, unsigned& outMaterialTextureSize)
{
if (HasMaterialTexture(tree))
{
auto materialTextureTree = dynamic_cast<IMaterialTexture*>(tree);
outMaterialTexture = materialTextureTree->GetMaterialTexture();
outMaterialTextureSize = materialTextureTree->GetMaterialTextureSize();
return true;
}
return false;
}
bool OctreeLoader::HasBlockTexture(BaseTree* tree)
{
return dynamic_cast<IBlockTexture*>(tree) != NULL;
}
bool OctreeLoader::GetBlockPointerPool(BaseTree* tree, std::string treeType, std::vector<unsigned8>& outBlockPointerPool)
{
if (HasBlockTexture(tree))
{
auto uTree = dynamic_cast<IBlockTexture*>(tree);
outBlockPointerPool = uTree->GetBlockPointerPool();
return true;
}
return false;
}
bool OctreeLoader::GetBlockPool(BaseTree* tree, std::string treeType, std::vector<unsigned8>& outBlockPool)
{
if (HasBlockTexture(tree))
{
auto uTree = dynamic_cast<IBlockTexture*>(tree);
outBlockPool = uTree->GetBlockPool();
return true;
}
return false;
}
bool OctreeLoader::HasAdditionalProperties(BaseTree* tree)
{
return dynamic_cast<IAdditionalProperties*>(tree) != NULL;
}
bool OctreeLoader::GetAdditionalProperties(BaseTree* tree, std::string treeType, std::string poolType, std::map<std::string, std::string>& outAdditionalProperties)
{
if (HasAdditionalProperties(tree))
{
auto uTree = dynamic_cast<IAdditionalProperties*>(tree);
outAdditionalProperties = uTree->GetAdditionalProperties();
}
// Some types have specific additional properties:
auto descr = TreeTypeParser::GetTreeTypeDescriptor(treeType);
std::string material = "MT_NONE";
if (descr.material == "c") material = "MT_COLOR";
else if (descr.material == "n") material = "MT_NORMAL";
else if (descr.material == "cn") material = "MT_COLORNORMAL";
else if (descr.material == "cnr") material = "MT_COLORNORMALREFLECTIVITY";
else if (descr.material == "co") material = "MT_COLOROPACITY";
outAdditionalProperties.insert(std::make_pair("Material", material));
if (descr.material == "n" || descr.material == "cn" || descr.material == "cnr") outAdditionalProperties.insert(std::make_pair("NormalSize", std::to_string(SmallNormal::BITS)));
std::string globalTypeString;
switch (descr.globalType)
{
case MULTIROOT: globalTypeString = "TT_MULTIROOT"; break;
case HIERARCHICAL: globalTypeString = (descr.additionalTypeInfo == "s") ? "TT_HIERARCHICALSHIFT" : "TT_HIERARCHICAL"; break;
case ONLYMATERIAL: globalTypeString = "TT_ONLYMATERIAL"; break;
case UNIQUEINDEX: globalTypeString = (descr.additionalTypeInfo != "" && descr.additionalTypeInfo[0] == 's') ? "TT_UNIQUEINDEXSHIFT" : "TT_UNIQUEINDEX"; break;
case RANDOM: globalTypeString = "TT_RANDOM"; break;
case BITTREES: globalTypeString = "TT_BITTREES"; break;
case STANDARD: default: globalTypeString = "TT_STANDARD"; break;
}
outAdditionalProperties.insert(std::pair<std::string, std::string>("TreeType", globalTypeString));
std::string poolTypeString;
PoolBuilderType poolTypeEnum = PoolBuilderFactory::GetType(poolType);
switch (poolTypeEnum)
{
case ORIGINAL: poolTypeString = "PT_ORIGINAL"; break;
case STANDARDPOOL: poolTypeString = "PT_STANDARD"; break;
case ADAPTIVEDIRECT1: poolTypeString = "PT_ADAPTIVEDIRECT1"; break;
case ADAPTIVELOOKUP1: poolTypeString = "PT_ADAPTIVELOOKUP1"; break;
case ADAPTIVEDIRECT2: poolTypeString = "PT_ADAPTIVEDIRECT2"; break;
case ADAPTIVELOOKUP2: poolTypeString = "PT_ADAPTIVELOOKUP2"; break;
case VIRTUALNODES: poolTypeString = "PT_VIRTUALNODES"; break;
}
outAdditionalProperties.insert(std::make_pair("PoolType", poolTypeString));
if (descr.globalType == UNIQUEINDEX)
{
std::string compressionType = "";
CompressionType cType = CompressedTextureFactory<MaterialLibraryPointer>::GetCompressionType(descr.textureCompressor);
if (cType == BASIC)
compressionType = "BASIC_PACK";
else if (cType == TIGHT)
compressionType = "TIGHT_PACK";
else if (cType == BLOCK)
compressionType = "BLOCK_PACK";
else if (cType == TIGHTBLOCK)
compressionType = "TIGHTBLOCK_PACK";
else if (cType == PALETTEBLOCK)
compressionType = "PALETTE_PACK";
else if (cType == DAGBASED)
compressionType = "DAGBASED_PACK";
else if (cType == MULTIROOTBASED)
compressionType = "MULTIROOTBASED_PACK";
outAdditionalProperties.insert(std::pair<std::string, std::string>("TextureCompression", compressionType));
}
if (descr.globalType == MULTIROOT)
{
outAdditionalProperties.insert(std::pair<std::string, std::string>("BitsPerTree", std::to_string(TreeTypeParser::GetBitsPerTree(descr))));
outAdditionalProperties.insert(std::pair<std::string, std::string>("BitsPerChannel", std::to_string(TreeTypeParser::GetBitsPerChannel(descr))));
}
return true;
}
bool OctreeLoader::GetPool(
std::vector<unsigned8>& outPool, unsigned& outPoolSize,
std::vector<unsigned8>& outMaterialTexture, unsigned& outMaterialTextureSize,
std::vector<unsigned8>& outMaterialPool, unsigned& outMaterialPoolSize,
std::vector<unsigned8>& outBlockPointerPool, std::vector<unsigned8>& outBlockPool,
std::map<std::string, std::string>& outAdditionalProperties)
{
return GetPool(SettingsParser::GetTreeTypeFromSettings(), SettingsParser::GetPoolTypeFromSettings(), SettingsParser::GetMaxLevelFromSettings(), SettingsParser::GetFilenameFromSettings(), SettingsParser::GetUsePoolCacheFromSettings(),
outPool, outPoolSize, outMaterialTexture, outMaterialTextureSize, outMaterialPool, outMaterialPoolSize,
outBlockPointerPool, outBlockPool,
outAdditionalProperties, SettingsParser::GetVerboseFromSettings());
}
bool OctreeLoader::GetPool(std::string treeType, std::string poolType, unsigned8 maxLevel, std::string filename, bool usePoolCache,
std::vector<unsigned8>& outPool, unsigned& outPoolSize,
std::vector<unsigned8>& outMaterialTexture, unsigned& outMaterialTextureSize,
std::vector<unsigned8>& outMaterialPool, unsigned& outMaterialPoolSize,
std::vector<unsigned8>& outBlockPointerPool, std::vector<unsigned8>& outBlockPool,
std::map<std::string, std::string>& outAdditionalProperties,
bool verbose)
{
unsigned globalType = TreeTypeParser::GetGlobalType(treeType);
bool succes = false;
switch (globalType)
{
case HIERARCHICAL: case BITTREES:
succes = OctreeLoader::GetHierarchicalPool(treeType, poolType, maxLevel, filename, usePoolCache, outPool, outPoolSize, outMaterialTexture, outMaterialTextureSize, outAdditionalProperties, verbose); break;
case ONLYMATERIAL:
succes = OctreeLoader::GetOnlyMaterialPool(treeType, poolType, maxLevel, filename, usePoolCache, outPool, outPoolSize, outMaterialPool, outMaterialPoolSize, outMaterialTexture, outMaterialTextureSize, outAdditionalProperties, verbose); break;
case UNIQUEINDEX:
succes = OctreeLoader::GetUniqueIndexPool(treeType, poolType, maxLevel, filename, usePoolCache, outPool, outPoolSize, outMaterialTexture, outMaterialTextureSize, outBlockPointerPool, outBlockPool, outAdditionalProperties, verbose); break;
default:
succes = OctreeLoader::GetStandardPool(treeType, poolType, maxLevel, filename, usePoolCache, outPool, outPoolSize, outAdditionalProperties, verbose); break;
}
return succes;
}
bool OctreeLoader::GetStandardPool(std::vector<unsigned8>& outPool, unsigned& outPoolSize, std::map<std::string, std::string>& outAdditionalProperties)
{
return GetStandardPool(
SettingsParser::GetTreeTypeFromSettings(), SettingsParser::GetPoolTypeFromSettings(), SettingsParser::GetMaxLevelFromSettings(), SettingsParser::GetFilenameFromSettings(), SettingsParser::GetUsePoolCacheFromSettings(),
outPool, outPoolSize, outAdditionalProperties, SettingsParser::GetVerboseFromSettings());
}
bool OctreeLoader::GetStandardPool(std::string treeType, std::string poolType, unsigned8 maxLevel, std::string filename, bool usePoolCache,
std::vector<unsigned8>& outPool, unsigned& outPoolSize, std::map<std::string, std::string>& outAdditionalProperties, bool verbose)
{
unsigned globalType = TreeTypeParser::GetGlobalType(treeType);
// Standard, Colored and Multiroot all use the same type of pool
if (globalType != STANDARD && globalType != MULTIROOT && globalType != RANDOM)
return false;
std::string poolFilename = GetFullFilename(treeType, maxLevel, filename);
if (usePoolCache)
{
// Try and read the pool cache
// Create a root of the correct type to try and read the pool
BaseTree* tree = CreateTree(treeType, maxLevel);
bool readSucces = ReadNodePool(tree, poolType, poolFilename, outPool, outPoolSize, verbose);
if (readSucces) readSucces &= GetAdditionalProperties(tree, treeType, poolType, outAdditionalProperties);
if (readSucces && verbose) PrintGPUMemoryRequirements(outPool.size(), 0, 0, 0);
delete tree;
if (readSucces)
return true;
}
// If cache shouldn't be used or loading failed, load the tree file and build the pool from it
BaseTree* tree = ReadCache(treeType, maxLevel, filename, verbose);
if (tree == NULL)
return false;
bool succes = BuildNodePool(tree, poolType, poolFilename, outPool, outPoolSize, verbose);
if (succes) succes &= GetAdditionalProperties(tree, treeType, poolType, outAdditionalProperties);
if (verbose && succes) PrintGPUMemoryRequirements(treeType, poolType, maxLevel, tree);
delete tree;
return succes;
}
bool OctreeLoader::GetHierarchicalPool(std::vector<unsigned8>& outPool, unsigned& outPoolSize,
std::vector<unsigned char>& outMaterialTexture, unsigned& outMaterialTextureSize,
std::map<std::string, std::string>& outAdditionalProperties)
{
return GetHierarchicalPool(
SettingsParser::GetTreeTypeFromSettings(), SettingsParser::GetPoolTypeFromSettings(), SettingsParser::GetMaxLevelFromSettings(), SettingsParser::GetFilenameFromSettings(), SettingsParser::GetUsePoolCacheFromSettings(),
outPool, outPoolSize, outMaterialTexture, outMaterialTextureSize, outAdditionalProperties, SettingsParser::GetVerboseFromSettings());
}
bool OctreeLoader::GetHierarchicalPool(std::string treeType, std::string poolType, unsigned8 maxLevel, std::string filename, bool usePoolCache,
std::vector<unsigned8>& outPool, unsigned& outPoolSize, std::vector<unsigned char>& outMaterialTexture, unsigned& outMaterialTextureSize,
std::map<std::string, std::string>& outAdditionalProperties,
bool verbose)
{
unsigned globalType = TreeTypeParser::GetGlobalType(treeType);
if (globalType != HIERARCHICAL && globalType != BITTREES)
return false;
std::string poolFilename = GetFullFilename(treeType, maxLevel, filename);
if (usePoolCache)
{
// Try and read the pool cache
// Create a root of the correct type to try and read the pool
BaseTree* tree = CreateTree(treeType, maxLevel);
bool readSucces = ReadNodePool(tree, poolType, poolFilename, outPool, outPoolSize, verbose);
if (readSucces) readSucces &= GetMaterialTexture(tree, treeType, outMaterialTexture, outMaterialTextureSize);
if (readSucces) readSucces &= GetAdditionalProperties(tree, treeType, poolType, outAdditionalProperties);
if (readSucces && verbose) PrintGPUMemoryRequirements(outPool.size(), outMaterialTexture.size(), 0, 0);
delete tree;
if (readSucces)
return true;
}
// If cache shouldn't be used or loading failed, load the tree file and build the pool from it
BaseTree* tree = ReadCache(treeType, maxLevel, filename, verbose);
if (tree == NULL)
return false;
bool succes = BuildNodePool(tree, poolType, poolFilename, outPool, outPoolSize, verbose);
succes &= GetMaterialTexture(tree, treeType, outMaterialTexture, outMaterialTextureSize);
if (succes) succes &= GetAdditionalProperties(tree, treeType, poolType, outAdditionalProperties);
if (verbose) PrintGPUMemoryRequirements(treeType, poolType, maxLevel, tree);
delete tree;
return succes;
}
bool OctreeLoader::GetOnlyMaterialPool(
std::vector<unsigned8>& outGeometryPool, unsigned& outGeometryPoolSize,
std::vector<unsigned8>& outMaterialPool, unsigned& outMaterialPoolSize,
std::vector<unsigned char>& outMaterialTexture, unsigned& outMaterialTextureSize,
std::map<std::string, std::string>& outAdditionalProperties)
{
return GetOnlyMaterialPool(
SettingsParser::GetTreeTypeFromSettings(), SettingsParser::GetPoolTypeFromSettings(), SettingsParser::GetMaxLevelFromSettings(), SettingsParser::GetFilenameFromSettings(), SettingsParser::GetUsePoolCacheFromSettings(),
outGeometryPool, outGeometryPoolSize, outMaterialPool, outMaterialPoolSize, outMaterialTexture, outMaterialTextureSize, outAdditionalProperties, SettingsParser::GetVerboseFromSettings());
}
bool OctreeLoader::GetOnlyMaterialPool(std::string treeType, std::string poolType, unsigned8 maxLevel, std::string filename, bool usePoolCache,
std::vector<unsigned8>& outGeometryPool, unsigned& outGeometryPoolSize,
std::vector<unsigned8>& outMaterialPool, unsigned& outMaterialPoolSize,
std::vector<unsigned char>& outMaterialTexture, unsigned& outMaterialTextureSize,
std::map<std::string, std::string>& outAdditionalProperties,
bool verbose)
{
unsigned globalType = TreeTypeParser::GetGlobalType(treeType);
if (globalType != ONLYMATERIAL)
return false;
std::string poolFilename = GetFullFilename(treeType, maxLevel, filename);
bool geometryReadSucces = false;
bool materialReadSucces = false;
if (usePoolCache)
{
// Try and read the pool cache for both the
// Create a root of the correct type to try and read the pool
BaseTree* geometryTree = CreateTree("s", maxLevel);
geometryReadSucces = ReadNodePool(geometryTree, poolType, GetFullFilename("s", maxLevel, filename), outGeometryPool, outGeometryPoolSize);
delete geometryTree;
BaseTree* materialTree = CreateTree(treeType, maxLevel);
materialReadSucces &= ReadNodePool(materialTree, poolType, poolFilename, outMaterialPool, outMaterialPoolSize, verbose);
if (materialReadSucces)
materialReadSucces &= GetMaterialTexture(materialTree, treeType, outMaterialTexture, outMaterialTextureSize);
if (materialReadSucces) materialReadSucces &= GetAdditionalProperties(materialTree, treeType, poolType, outAdditionalProperties);
delete materialTree;
if (geometryReadSucces && materialReadSucces)
return true;
}
// If cache shouldn't be used or loading failed, load the tree file and build the pool from it
if (!geometryReadSucces)
{
BaseTree* geometryTree = ReadCache("s", maxLevel, filename, verbose);
if (geometryTree == NULL)
return false;
geometryReadSucces = BuildNodePool(geometryTree, poolType, poolFilename, outGeometryPool, outGeometryPoolSize, verbose);
delete geometryTree;
}
if (!materialReadSucces)
{
BaseTree* materialTree = ReadCache(treeType, maxLevel, filename, verbose);
if (materialTree == NULL)
return false;
materialReadSucces = BuildNodePool(materialTree, poolType, poolFilename, outMaterialPool, outMaterialPoolSize, verbose);
materialReadSucces &= GetMaterialTexture(materialTree, treeType, outMaterialTexture, outMaterialTextureSize);
if (materialReadSucces) materialReadSucces &= GetAdditionalProperties(materialTree, treeType, poolType, outAdditionalProperties);
delete materialTree;
}
return materialReadSucces && geometryReadSucces;
}
bool OctreeLoader::GetUniqueIndexPool(
std::vector<unsigned8>& outPool, unsigned& outPoolSize,
std::vector<unsigned8>& outMaterialTexture, unsigned& outMaterialTextureSize,
std::vector<unsigned8>& outBlockPointerPool, std::vector<unsigned8>& outBlockPool,
std::map<std::string, std::string>& outAdditionalProperties)
{
return GetUniqueIndexPool(
SettingsParser::GetTreeTypeFromSettings(), SettingsParser::GetPoolTypeFromSettings(), SettingsParser::GetMaxLevelFromSettings(), SettingsParser::GetFilenameFromSettings(), SettingsParser::GetUsePoolCacheFromSettings(),
outPool, outPoolSize, outMaterialTexture, outMaterialTextureSize, outBlockPointerPool, outBlockPool, outAdditionalProperties, SettingsParser::GetVerboseFromSettings());
}
bool OctreeLoader::GetUniqueIndexPool(std::string treeType, std::string poolType, unsigned8 maxLevel, std::string filename, bool usePoolCache,
std::vector<unsigned8>& outPool, unsigned& outPoolSize,
std::vector<unsigned8>& outMaterialTexture, unsigned& outMaterialTextureSize,
std::vector<unsigned8>& outBlockPointerPool, std::vector<unsigned8>& outBlockPool,
std::map<std::string, std::string>& outAdditionalProperties,
bool verbose)
{
unsigned globalType = TreeTypeParser::GetGlobalType(treeType);
if (globalType != UNIQUEINDEX)
return false;
std::string poolFilename = GetFullFilename(treeType, maxLevel, filename);
if (usePoolCache)
{
// Try and read the pool cache
// Create a root of the correct type to try and read the pool
BaseTree* tree = CreateTree(treeType, maxLevel);
bool readSucces = ReadNodePool(tree, poolType, poolFilename, outPool, outPoolSize, verbose);
if (readSucces) readSucces &= GetMaterialTexture(tree, treeType, outMaterialTexture, outMaterialTextureSize);
if (readSucces) readSucces &= GetBlockPointerPool(tree, treeType, outBlockPointerPool);
if (readSucces) readSucces &= GetBlockPool(tree, treeType, outBlockPool);
if (readSucces) readSucces &= GetAdditionalProperties(tree, treeType, poolType, outAdditionalProperties);
if (readSucces && verbose)
PrintGPUMemoryRequirements(outPool.size(), outMaterialTexture.size(), outBlockPool.size(), outBlockPointerPool.size());
delete tree;
if (readSucces)
return true;
}
// If cache shouldn't be used or loading failed, load the tree file and build the pool from it
BaseTree* tree = ReadCache(treeType, maxLevel, filename, verbose);
if (tree == NULL)
return false;
bool succes = BuildNodePool(tree, poolType, poolFilename, outPool, outPoolSize, verbose);
if (succes) succes &= GetMaterialTexture(tree, treeType, outMaterialTexture, outMaterialTextureSize);
if (succes) succes &= GetBlockPointerPool(tree, treeType, outBlockPointerPool);
if (succes) succes &= GetBlockPool(tree, treeType, outBlockPool);
if (succes) succes &= GetAdditionalProperties(tree, treeType, poolType, outAdditionalProperties);
if (verbose) PrintGPUMemoryRequirements(treeType, poolType, maxLevel, tree);
delete tree;
return succes;
}
size_t OctreeLoader::GetGPUMemoryRequirements()
{
return OctreeLoader::GetGPUMemoryRequirements(SettingsParser::GetTreeTypeFromSettings(), SettingsParser::GetPoolTypeFromSettings(), SettingsParser::GetMaxLevelFromSettings(), SettingsParser::GetFilenameFromSettings());
}
size_t OctreeLoader::GetGPUMemoryRequirements(std::string treeType, std::string poolType, unsigned8 maxLevel, std::string filename)
{
BaseTree* tree = OctreeLoader::ReadCache(treeType, maxLevel, filename);
return GetGPUMemoryRequirements(treeType, poolType, tree);
}
size_t OctreeLoader::GetGPUMemoryRequirements(std::string treeType, std::string poolType, BaseTree* tree)
{
// Every tree has the nodepool.
BasePoolBuilder<BaseTree>* builder = PoolBuilderFactory::Create(poolType);
size_t treePoolSize = builder->GetPoolSize(tree);
delete builder;
size_t res = treePoolSize;
if (HasMaterialTexture(tree))
{
auto materialTree = dynamic_cast<IMaterialTexture*>(tree);
size_t materialTextureSize = materialTree->GetMaterialTextureSize();
res += materialTextureSize * materialTextureSize * materialTree->GetMaterialTextureChannelsPerPixel(); // 2D texture with the given channels per pixel
}
if (HasBlockTexture(tree))
{
auto blockTextureTree = dynamic_cast<IBlockTexture*>(tree);
size_t blockPointerPoolMemoryRequirements = blockTextureTree->GetBlockPointerPoolSize();
size_t blockPoolMemoryRequirements = blockTextureTree->GetBlockPoolSize();
size_t blockTextureMemoryRequirements = blockPointerPoolMemoryRequirements + blockPoolMemoryRequirements;
res += blockTextureMemoryRequirements;
printf("Block texture required %.2f MB. (main: %.2f MB, additional: %.2f MB)\n",
(double)blockTextureMemoryRequirements / (1024.0 * 1024.0),
(double)blockPoolMemoryRequirements / (1024.0 * 1024.0),
(double)blockPointerPoolMemoryRequirements / (1024.0 * 1024.0));
}
return res;
}
size_t OctreeLoader::GetMainTreeGPUMemoryRequirements()
{
std::string treeType = SettingsParser::GetTreeTypeFromSettings();
BaseTree* tree = OctreeLoader::ReadCache(treeType, SettingsParser::GetMaxLevelFromSettings(), SettingsParser::GetFilenameFromSettings());
size_t res = GetGPUMemoryRequirements(treeType, SettingsParser::GetPoolTypeFromSettings(), tree);
return res;
}
size_t OctreeLoader::GetMainTreeGPUMemoryRequirements(std::string treeType, std::string poolType, BaseTree* tree)
{
BasePoolBuilder<BaseTree>* builder = PoolBuilderFactory::Create(poolType);
size_t treePoolSize = builder->GetPoolSize(tree);
delete builder;
return TEXTURESIZE * TEXTURESIZE * MathHelper::DivideRoundUp(treePoolSize, TEXTURESIZE * TEXTURESIZE);
}
void OctreeLoader::PrintGPUMemoryRequirements(std::string treeType, std::string poolType, unsigned8 maxLevel, BaseTree* tree)
{
size_t memoryRequirements = GetGPUMemoryRequirements(treeType, poolType, tree);
printf("Tree requires %11zu bytes (%8.2f MB).\n", memoryRequirements, (double)memoryRequirements / 1048576.0);
}
void OctreeLoader::PrintGPUMemoryRequirements(size_t poolSize, size_t materialTextureSize, size_t blockPoolSize, size_t blockPointerPoolSize)
{
size_t memoryRequirements = poolSize + materialTextureSize + blockPoolSize + blockPointerPoolSize;
printf("Tree requires %11zu bytes (%8.2f MB).\n", memoryRequirements, (double)memoryRequirements / 1048576.0);
}
std::string OctreeLoader::GetFullFilename()
{
PropertyLoader::Create();
auto propertyLoader = PropertyLoader::Instance();
std::string filename = propertyLoader->GetProperty("dag_file");
unsigned8 maxLevel = (unsigned8)std::stoi(propertyLoader->GetProperty("shader_max_level"));
std::string treeType = propertyLoader->GetProperty("octree_type");
return GetFullFilename(treeType, maxLevel, filename);
}
std::string OctreeLoader::GetFullFilename(std::string treeType, unsigned8 maxLevel, std::string filename)
{
// Hack: make sure filenames are consistent for soem special tree types
if (treeType == "m") treeType = "m8";
// Convert compression method to normalized compression method
TreeTypeDescriptor descr = TreeTypeParser::GetTreeTypeDescriptor(treeType);
if (descr.quantizer != "")
{
StringHelper::Replace(treeType, descr.quantizer, ColorQuantizerFactory::GetNormalizedType(descr.quantizer));
}
if (descr.globalType == UNIQUEINDEX && descr.additionalTypeInfo != "")
{
unsigned8 lod = TreeTypeParser::GetLevelsWithoutMaterials(descr);
if (lod != 0)
StringHelper::Replace(treeType, descr.additionalTypeInfo, std::to_string(lod) + "lod");
}
return filename + "_" + std::to_string(maxLevel) + "_" + treeType;
}
BaseTree* OctreeLoader::CreateTree(std::string type, unsigned8 maxLevel)
{
BaseTree* tree = NULL;
TreeTypeDescriptor descr = TreeTypeParser::GetTreeTypeDescriptor(type);
switch (descr.globalType)
{
case HIERARCHICAL:
{
if (descr.material == "c")
{
if (descr.additionalTypeInfo == "s")
tree = new HierarchicalShiftingColoredTree(maxLevel);
else
tree = new MaterialLibraryTree<Color, ColorCompare>(maxLevel);
}
else if (descr.material == "n")
tree = new MaterialLibraryTree<SmallNormal, NormalCompare, SmallNormal::BYTES>(maxLevel);
else if (descr.material == "cn")
tree = new MaterialLibraryTree<ColorAndNormal, ColorAndNormalCompare, ColorAndNormal::CHANNELSPERPIXEL>(maxLevel);
else if (descr.material == "cnr")
tree = new MaterialLibraryTree<ColorAndNormalAndValue, ColorAndNormalAndValueCompare, ColorAndNormalAndValue::CHANNELSPERPIXEL>(maxLevel);
else if (descr.material == "co")
tree = new MaterialLibraryTree<ColorAndOpacity, ColorAndOpacityCompare, ColorAndOpacity::CHANNELSPERPIXEL>(maxLevel);
break;
}
case ONLYMATERIAL:
{
tree = new HierarchicalColorsOnlyTree(maxLevel);
break;
}
case UNIQUEINDEX:
{
unsigned8 levelsWithoutMaterials = TreeTypeParser::GetLevelsWithoutMaterials(descr);
if (descr.additionalTypeInfo != "" && descr.additionalTypeInfo[0] == 's')
{
assert(descr.material != "n");
auto texture = CompressedTextureFactory<SignedIntMaterial>::GetCompressedTexture(descr.textureCompressor);
tree = new UniqueIndexShiftTree<Color, ColorCompare>(maxLevel, texture, levelsWithoutMaterials);
}
else
{
auto texture = CompressedTextureFactory<MaterialLibraryPointer>::GetCompressedTexture(descr.textureCompressor);
if (descr.material == "c")
tree = new MaterialLibraryUniqueIndexTree<Color, ColorCompare>(maxLevel, texture, levelsWithoutMaterials);
else if (descr.material == "n")
tree = new MaterialLibraryUniqueIndexTree<SmallNormal, NormalCompare, SmallNormal::CHANNELSPERPIXEL>(maxLevel, texture, levelsWithoutMaterials);
else if (descr.material == "cn")
tree = new MaterialLibraryUniqueIndexTree<ColorAndNormal, ColorAndNormalCompare, ColorAndNormal::CHANNELSPERPIXEL>(maxLevel, texture, levelsWithoutMaterials);
else if (descr.material == "cnr")
tree = new MaterialLibraryUniqueIndexTree<ColorAndNormalAndValue, ColorAndNormalAndValueCompare, ColorAndNormalAndValue::CHANNELSPERPIXEL>(maxLevel, texture, levelsWithoutMaterials);
else if (descr.material == "co")
tree = new MaterialLibraryUniqueIndexTree<ColorAndOpacity, ColorAndOpacityCompare, ColorAndOpacity::CHANNELSPERPIXEL>(maxLevel, texture, levelsWithoutMaterials);
else
delete texture;
}
break;
}
case MULTIROOT:
{
std::vector<std::string> additionalTypes(8);
additionalTypes[0] = "1";
additionalTypes[1] = "2";
additionalTypes[2] = "3";
additionalTypes[3] = "4";
additionalTypes[4] = "5";
additionalTypes[5] = "6";
additionalTypes[6] = "7";
additionalTypes[7] = "8";
if (descr.additionalTypeInfo == "cc")
{
tree = new LeafMaterialMultiRootTree<ColorChannel>(maxLevel, 3);
}
else if (CollectionHelper::Contains(additionalTypes, descr.additionalTypeInfo))
{
unsigned8 bitsPerChannel = TreeTypeParser::GetBitsPerChannel(descr);
tree = new MultiRootTree<>(maxLevel, 3 * bitsPerChannel);
}
else
{
unsigned8 bitsPerChannel = TreeTypeParser::GetBitsPerChannel(descr);
unsigned8 bitsPerTree = TreeTypeParser::GetBitsPerTree(descr);
unsigned8 treesPerChannel = bitsPerChannel / bitsPerTree + (bitsPerChannel % bitsPerTree == 0 ? 0 : 1);
switch (bitsPerTree)
{
case 1: tree = new LeafMaterialMultiRootTree<BitsMaterial<1>>(maxLevel, 3 * treesPerChannel); break;
case 2: tree = new LeafMaterialMultiRootTree<BitsMaterial<2>>(maxLevel, 3 * treesPerChannel); break;
case 3: tree = new LeafMaterialMultiRootTree<BitsMaterial<3>>(maxLevel, 3 * treesPerChannel); break;
case 4: tree = new LeafMaterialMultiRootTree<BitsMaterial<4>>(maxLevel, 3 * treesPerChannel); break;
case 5: tree = new LeafMaterialMultiRootTree<BitsMaterial<5>>(maxLevel, 3 * treesPerChannel); break;
case 6: tree = new LeafMaterialMultiRootTree<BitsMaterial<6>>(maxLevel, 3 * treesPerChannel); break;
case 7: tree = new LeafMaterialMultiRootTree<BitsMaterial<7>>(maxLevel, 3 * treesPerChannel); break;
case 8: tree = new LeafMaterialMultiRootTree<BitsMaterial<8>>(maxLevel, 3 * treesPerChannel); break;
}
}
break;
}
case RANDOM:
{
tree = new MaterialTree<BitsMaterial<1>, HashComparer<BitsMaterial<1>>>(maxLevel); break;
}
case BITTREES:
{
if (descr.additionalTypeInfo == "l")
tree = new MaterialLibraryMultiRoot<Color, ColorCompare>(maxLevel);
break;
}
default:
{
tree = new Tree<>(maxLevel);
break;
}
}
return tree;
}

View File

@@ -0,0 +1,109 @@
#pragma once
#include "OctreeBuilderStatistics.h"
#include "../Defines.h"
#include "../../inc/glm/vec3.hpp"
#include <map>
#include <string>
class BaseTree;
// Singleton wrapper that reads the settings and creates the correct octreebuilder
class OctreeLoader
{
public:
static const size_t TEXTURESIZE = 1024;
static BaseTree* CreateTree(std::string type, unsigned8 maxLevel);
// Reads the settings and verifies that the current file exists. Returns false if usecache is turned off.
static bool VerifyCache();
// Verify the cache. Returns true if the cache is valid.
static bool VerifyCache(std::string treeType, unsigned8 maxLevel, std::string filename);
static BaseTree* ReadCache();
static BaseTree* ReadCache(std::string treeType, unsigned8 maxLevel, std::string filename, bool verbose = false);
static void DeleteCache(std::string treeType, unsigned8 maxLevel, std::string filename);
static bool WriteCache(BaseTree* tree, std::string treeType, std::string filename, bool verbose);
static bool VerifyPool();
static bool VerifyPool(std::string treeType, unsigned8 maxLevel, std::string filename);
static bool GetPool(
std::vector<unsigned8>& outPool, unsigned& outPoolSize,
std::vector<unsigned8>& outMaterialTexture, unsigned& outMaterialTextureSize,
std::vector<unsigned8>& outMaterialPool, unsigned& outMaterialPoolSize,
std::vector<unsigned8>& outBlockPointerPool, std::vector<unsigned8>& outBlockPool,
std::map<std::string, std::string>& outAdditionalProperties);
static bool GetPool(std::string treeType, std::string poolType, unsigned8 maxLevel, std::string filename, bool usePoolCache,
std::vector<unsigned8>& outPool, unsigned& outPoolSize,
std::vector<unsigned8>& outMaterialTexture, unsigned& outMaterialTextureSize,
std::vector<unsigned8>& outMaterialPool, unsigned& outMaterialPoolSize,
std::vector<unsigned8>& outBlockPointerPool, std::vector<unsigned8>& outBlockPool,
std::map<std::string, std::string>& outAdditionalProperties,
bool verbose = false);
static bool GetStandardPool(
std::vector<unsigned8>& outPool, unsigned& outPoolSize, std::map<std::string, std::string>& outAdditionalProperties);
static bool GetStandardPool(std::string treeType, std::string poolType, unsigned8 maxLevel, std::string filename, bool usePoolCache,
std::vector<unsigned8>& outPool, unsigned& outPoolSize, std::map<std::string, std::string>& outAdditionalProperties, bool verbose = false);
static bool GetHierarchicalPool(
std::vector<unsigned8>& outPool, unsigned& outPoolSize,
std::vector<unsigned8>& outMaterialTexture, unsigned& outMaterialTextureSize,
std::map<std::string, std::string>& outAdditionalProperties);
static bool GetHierarchicalPool(std::string treeType, std::string poolType, unsigned8 maxLevel, std::string filename, bool usePoolCache,
std::vector<unsigned8>& outPool, unsigned& outPoolSize,
std::vector<unsigned8>& outMaterialTexture, unsigned& outMaterialTextureSize,
std::map<std::string, std::string>& outAdditionalProperties,
bool verbose = false);
static bool GetOnlyMaterialPool(
std::vector<unsigned8>& outGeometryPool, unsigned& outGeometryPoolSize,
std::vector<unsigned8>& outMaterialPool, unsigned& outMaterialPoolSize,
std::vector<unsigned8>& outMaterialTexture, unsigned& outMaterialTextureSize,
std::map<std::string, std::string>& outAdditionalProperties);
static bool GetOnlyMaterialPool(std::string treeType, std::string poolType, unsigned8 maxLevel, std::string filename, bool usePoolCache,
std::vector<unsigned8>& outGeometryPool, unsigned& outGeometryPoolSize,
std::vector<unsigned8>& outMaterialPool, unsigned& outMaterialPoolSize,
std::vector<unsigned8>& outMaterialTexture, unsigned& outMaterialTextureSize,
std::map<std::string, std::string>& outAdditionalProperties,
bool verbose = false);
static bool GetUniqueIndexPool(
std::vector<unsigned8>& outPool, unsigned& outPoolSize,
std::vector<unsigned8>& outMaterialTexture, unsigned& outMaterialTextureSize,
std::vector<unsigned8>& outBlockPointerPool, std::vector<unsigned8>& outBlockPool,
std::map<std::string, std::string>& outAdditionalProperties);
static bool GetUniqueIndexPool(std::string treeType, std::string poolType, unsigned8 maxLevel, std::string filename, bool usePoolCache,
std::vector<unsigned8>& outPool, unsigned& outPoolSize,
std::vector<unsigned8>& outMaterialTexture, unsigned& outMaterialTextureSize,
std::vector<unsigned8>& outBlockPointerPool, std::vector<unsigned8>& outBlockPool,
std::map<std::string, std::string>& outAdditionalProperties,
bool verbose = false);
// Returns the GPU memory requirements in bytes for the current settings (returns 0 if no tree is found)
static size_t GetGPUMemoryRequirements();
static size_t GetGPUMemoryRequirements(std::string treeType, std::string poolType, unsigned8 maxLevel, std::string filename);
static size_t GetGPUMemoryRequirements(std::string treeType, std::string poolType, BaseTree* tree);
static size_t GetMainTreeGPUMemoryRequirements();
static size_t GetMainTreeGPUMemoryRequirements(std::string treeType, std::string poolType, BaseTree* tree);
static std::string GetFullFilename();
static std::string GetFullFilename(std::string treeType, unsigned8 maxLevel, std::string filename);
private:
static bool BuildNodePool(BaseTree* tree, std::string poolType, std::string poolFullFilename, std::vector<unsigned8>& outPool, unsigned& outPoolSize, bool verbose = false);
static bool ReadNodePool(BaseTree* tree, std::string poolType, std::string poolFullFilename, std::vector<unsigned8>& outPool, unsigned& outPoolSize, bool verbose = false);
static bool GetMaterialTexture(BaseTree* tree, std::string treeType, std::vector<unsigned8>& outMaterialTexture, unsigned& outMaterialTextureSize);
static bool GetBlockPointerPool(BaseTree* tree, std::string treeType, std::vector<unsigned8>& outBlockPointerPool);
static bool GetBlockPool(BaseTree* tree, std::string treeType, std::vector<unsigned8>& outBlockPool);
static bool GetAdditionalProperties(BaseTree* tree, std::string treeType, std::string poolType, std::map<std::string, std::string>& outAdditionalProperties);
static bool HasMaterialTexture(BaseTree* treeType);
static bool HasBlockTexture(BaseTree* treeType);
static bool HasAdditionalProperties(BaseTree* treeType);
static size_t CeilToTextureSize(size_t size);
static void PrintGPUMemoryRequirements(std::string treeType, std::string poolType, unsigned8 maxLevel, BaseTree* tree);
static void PrintGPUMemoryRequirements(size_t poolSize, size_t materialTextureSize, size_t blockPoolSize, size_t blockPointerPoolSize);
};

View File

@@ -0,0 +1,76 @@
#pragma once
#include "../../scene/PoolBuilder/StandardPoolBuilder.h"
#include "../../scene/PoolBuilder/AdaptivePointerPoolBuilder.h"
#include "../../scene/PoolBuilder/OriginalPoolBuilder.h"
#include "../../scene/PoolBuilder/VirtualNodePoolBuilder.h"
enum PoolBuilderType
{
ORIGINAL, STANDARDPOOL, ADAPTIVELOOKUP1, ADAPTIVEDIRECT1, ADAPTIVELOOKUP2, ADAPTIVEDIRECT2, VIRTUALNODES
};
class PoolBuilderFactory
{
public:
static PoolBuilderType GetType(std::string type)
{
if (type == "o") return ORIGINAL;
if (type == "s") return STANDARDPOOL;
if (type == "al" || type.substr(0, 3) == "al2") return ADAPTIVELOOKUP2;
if (type == "ad" || type.substr(0, 3) == "ad2") return ADAPTIVEDIRECT2;
if (type.substr(0, 3) == "al1") return ADAPTIVELOOKUP1;
if (type.substr(0, 3) == "ad1") return ADAPTIVEDIRECT1;
if (type == "v") return VIRTUALNODES;
return STANDARDPOOL;
}
static BasePoolBuilder<BaseTree>* Create(std::string strType)
{
PoolBuilderType type = GetType(strType);
if (type == ADAPTIVEDIRECT1 || type == ADAPTIVEDIRECT2 || type == ADAPTIVELOOKUP1 || type == ADAPTIVELOOKUP2)
{
unsigned8 maskSize = (type == ADAPTIVEDIRECT1 || type == ADAPTIVELOOKUP1) ? 1 : 2;
bool useLookupTable = type == ADAPTIVELOOKUP1 || type == ADAPTIVELOOKUP2;
std::vector<unsigned8> bitSizes = maskSize == 1 ? std::vector<unsigned8> { 1 } : std::vector<unsigned8>{ 1, 2, 3 };
if (strType.length() > 3)
{
unsigned8 requiredNums = (unsigned8)(BitHelper::Exp2(maskSize) - 1);
std::string bitSizesStr = strType.substr(3, requiredNums);
for (unsigned8 i = 0; i < BitHelper::Exp2(maskSize) - 1; i++)
bitSizes[i] = bitSizesStr[i] - '0';
}
if (maskSize == 1)
return new AdaptivePointerPoolBuilder(useLookupTable, 1, bitSizes[0]);
else
return new AdaptivePointerPoolBuilder(useLookupTable, 2, bitSizes[0], bitSizes[1], bitSizes[2]);
}
switch (type)
{
case ORIGINAL: return new OriginalPoolBuilder(); break;
case VIRTUALNODES: return new VirtualNodePoolBuilder(); break;
case STANDARDPOOL: default: return new StandardPoolBuilder(); break;
}
}
static std::string GetReadableName(std::string strType)
{
PoolBuilderType type = GetType(strType);
switch (type)
{
case ORIGINAL: return "original";
case STANDARDPOOL: return "standard";
case ADAPTIVELOOKUP2: return "adaptive \\w lookup table";
case ADAPTIVEDIRECT2: return "adaptive \\w direct pointers";
case ADAPTIVELOOKUP1: return "adaptive \\w lookup table";
case ADAPTIVEDIRECT1: return "adaptive \\w direct pointers";
case VIRTUALNODES: return "virtual nodes";
default: return "unknown";
}
}
// Returns a string that can be used as a regex to match all compressed texture types
static std::string GetRegexMatcher()
{
return std::string("o|s|ad(1[1-4]?|2([1-4][1-4][1-4])?)|al(1[1-4]?|2([1-4][1-4][1-4])?)|v");
}
};

View File

@@ -0,0 +1,109 @@
#include "RandomOctreeBuilder.h"
#include "../Util/Stopwatch.h"
#include "OctreeLoader.h"
#include "../../inc/tbb/parallel_for.h"
RandomOctreeBuilder::RandomOctreeBuilder() :
BaseMaterialOctreeBuilder(),
mTree(NULL),
mCurPassTree(NULL),
mCurPassTreeCoord(glm::uvec3(0))
{}
RandomOctreeBuilder::~RandomOctreeBuilder() {}
std::string RandomOctreeBuilder::GetTreeType() { return "r"; }
void RandomOctreeBuilder::InitTree()
{
mTree = new MaterialTree<BitsMaterial<1>, HashComparer<BitsMaterial<1>>>(GetTreeDepth());
}
void RandomOctreeBuilder::FinalizeTree()
{
// Convert the octree to a DAG
Stopwatch watch;
if (verbose) printf("Converting final tree to DAG...\n");
watch.Reset();
mTree->ToDAG();
if (verbose) printf("Done in %u ms, %llu nodes left.\n", (unsigned)(watch.GetTime() * 1000), (unsigned64)mTree->GetNodeCount());
}
void RandomOctreeBuilder::TerminateTree()
{
OctreeLoader::WriteCache(mTree, GetTreeType(), GetOutputFile(), verbose);
delete mTree;
}
void RandomOctreeBuilder::InitCurPassTree(glm::uvec3 coord)
{
mCurPassTree = new MaterialTree<Color, ColorCompare>(GetSinglePassTreeDepth());
mCurPassTreeCoord = coord;
}
void RandomOctreeBuilder::FinalizeCurPassTree(glm::uvec3 coord)
{
Stopwatch watch;
unsigned8 mainTreeLevel = mTree->GetMaxLevel() - mCurPassTree->GetMaxLevel();
if (mCurPassTree->GetNodeCount() > 1) // Only append the tree (and compress) if it is not empty
{
//std::vector<BitsMaterial<1>> randomMaterials(mCurPassTree->GetNodeCount());
//tbb::parallel_for(size_t(0), randomMaterials.size(), [&](size_t i) { randomMaterials[i] = BitsMaterial<1>((std::rand() < (RAND_MAX / 2)) ? 1 : 0); });
//mCurPassTree->SetMaterials(randomMaterials);
mCurPassTree->PropagateMaterials([](const std::vector<Color>& materials, const std::vector<float>& weights){ return Color::WeightedAverage(materials, weights); });
std::vector<Color> colors = mCurPassTree->GetMaterials();
std::vector<BitsMaterial<1>> bitMaterials(mCurPassTree->GetNodeCount());
unsigned8 shift = 0;
tbb::parallel_for(size_t(0), bitMaterials.size(), [&](size_t i) { bitMaterials[i] = BitsMaterial<1>((colors[i].GetColor().r & (1 << shift)) >> shift); });
auto mCurPassBitTree = new MaterialTree<BitsMaterial<1>, HashComparer<BitsMaterial<1>>>(mCurPassTree->GetMaxLevel());
mCurPassBitTree->MoveShallow(mCurPassTree);
mCurPassBitTree->SetMaterials(bitMaterials);
delete mCurPassTree;
if (mainTreeLevel == 0) // Means we just constructed the root, so no need to append
{
delete mTree;
mTree = mCurPassBitTree;
}
else
{
//Convert the subtree to a DAG first, this saved time when appending and converting the total tree
//Benchmark (Total build time for subtrees of depth 10, final tree of depth 12, Release mode with pool):
// 209.922 seconds without early converting
// 163.645 seconds with early converting
if (verbose) printf("Converting subtree to DAG...\n");
watch.Reset();
mCurPassBitTree->ToDAG();
if (verbose) printf("Converting took %d ms.\n", (int)(watch.GetTime() * 1000));
if (verbose) printf("Appending subtree... ");
mTree->Append(mCurPassTreeCoord, mainTreeLevel, mCurPassBitTree);
delete mCurPassBitTree;
if (verbose) printf("Converting current tree to DAG...\n");
mTree->ToDAG(mainTreeLevel);
}
}
else
{
delete mCurPassTree;
}
}
void RandomOctreeBuilder::AddNode(const glm::uvec3& coordinate, const Color& color)
{
mCurPassTree->AddLeafNode(coordinate, color);
}
std::vector<size_t> RandomOctreeBuilder::GetOctreeNodesPerLevel()
{
return mTree->GetOctreeNodesPerLevel();
}
std::vector<size_t> RandomOctreeBuilder::GetNodesPerLevel()
{
return mTree->GetNodesPerLevel();
}

View File

@@ -0,0 +1,38 @@
#pragma once
#include "BaseMaterialOctreeBuilder.h"
#include "../../scene/Octree/MaterialTree.h"
#include "../Comparers.h"
#include "../../scene/Material/BitsMaterial.h"
#include "../../scene/Material/Color.h"
class RandomOctreeBuilder : public BaseMaterialOctreeBuilder<Color>
{
public:
RandomOctreeBuilder();
~RandomOctreeBuilder() override;
std::string GetTreeType() override;
protected:
// Initialize the main tree
void InitTree() override;
void FinalizeTree() override;
// Step to finalize the main tree (for example storing it to a file)
void TerminateTree() override;
// Initialize the tree for the current pass.
void InitCurPassTree(glm::uvec3 coord) override;
// Terminate the tree in the current pass. This means it should also be appended to the main tree and deleted
void FinalizeCurPassTree(glm::uvec3 coord) override;
// Should add a node to the current pass tree at the given coordinate and color
void AddNode(const glm::uvec3& coordinate, const Color& color) override;
std::vector<size_t> GetOctreeNodesPerLevel() override;
std::vector<size_t> GetNodesPerLevel() override;
private:
MaterialTree<BitsMaterial<1>, HashComparer<BitsMaterial<1>>>* mTree;
MaterialTree<Color, ColorCompare>* mCurPassTree;
glm::uvec3 mCurPassTreeCoord;
};

View File

@@ -0,0 +1,22 @@
#include "SettingsParser.h"
#include "../../PropertyLoader.h"
PropertyLoader* GetPropertyLoader()
{
PropertyLoader::Create();
return PropertyLoader::Instance();
}
std::string SettingsParser::GetTreeTypeFromSettings() { return GetPropertyLoader()->GetProperty("octree_type"); }
std::string SettingsParser::GetPoolTypeFromSettings() { return GetPropertyLoader()->GetProperty("pool_type"); }
unsigned8 SettingsParser::GetMaxLevelFromSettings() { return (unsigned8)GetPropertyLoader()->GetIntProperty("shader_max_level"); }
std::string SettingsParser::GetFilenameFromSettings() { return GetPropertyLoader()->GetProperty("dag_file"); }
bool SettingsParser::GetUsePoolCacheFromSettings()
{
// Only use the pool cache if the octreebuilder cache is used as well
return GetPropertyLoader()->GetBoolProperty("renderer_usecache") && GetPropertyLoader()->GetBoolProperty("octreebuilder_usecache");
}
bool SettingsParser::GetUseCacheFromSettings() { return GetPropertyLoader()->GetBoolProperty("octreebuilder_usecache"); }
bool SettingsParser::GetForceRebuildFromSettings() { return GetPropertyLoader()->GetBoolProperty("octreebuilder_forcerebuild"); }
bool SettingsParser::GetVerboseFromSettings() { return GetPropertyLoader()->GetBoolProperty("verbose"); }

View File

@@ -0,0 +1,17 @@
#pragma once
#include <string>
#include "../Defines.h"
class SettingsParser
{
public:
static std::string GetTreeTypeFromSettings();
static std::string GetPoolTypeFromSettings();
static unsigned8 GetMaxLevelFromSettings();
static std::string GetFilenameFromSettings();
static bool GetUsePoolCacheFromSettings();
static bool GetUseCacheFromSettings();
static bool GetForceRebuildFromSettings();
static bool GetVerboseFromSettings();
};

View File

@@ -0,0 +1,122 @@
#include "StandardOctreeBuilder.h"
#include "../Util/Stopwatch.h"
#include "OctreeLoader.h"
#define DAGFINALTREE
StandardOctreeBuilder::StandardOctreeBuilder() :
BaseStandardOctreeBuilder(),
mTree(NULL)
{}
StandardOctreeBuilder::~StandardOctreeBuilder() {}
std::string StandardOctreeBuilder::GetTreeType() { return "s"; }
void StandardOctreeBuilder::FinalizeTree()
{
// Read all subtrees from cache and append them
if (!IsSinglePass())
{
Stopwatch watch;
mTree = new Tree<>(GetTreeDepth());
int i = 1;
for (const glm::uvec3& coord : GetValidCoords())
{
if (verbose) printf("Reading subtree %u / %u at (%u, %u, %u) from cache...\n", i, (unsigned32)(GetValidCoords().size()), coord.x, coord.y, coord.z);
Tree<>* subTree = (Tree<>*)OctreeLoader::ReadCache(GetTreeType(), GetSinglePassTreeDepth(), GetSinglePassTreeFilename(coord), verbose);
if (subTree != NULL)
{
if (verbose) printf("Appending subtree... ");
watch.Reset();
mTree->AppendAndMerge(coord, GetAppendedTreeLevel(), subTree);
//mTree->Append(mCurPassTreeCoord, mainTreeLevel, mCurPassTree);
delete subTree;
if (verbose) printf("Appended subtree in %d ms.\n", (int)(watch.GetTime() * 1000));
}
//mTree->SortNodes();
//#ifdef DAGFINALTREE
// if (verbose) printf("Converting current tree to DAG...\n");
// mTree->ToDAG(mainTreeLevel);
//#endif
i++;
}
// Delete the cache files
if (verbose) printf("Deleting cache...");
watch.Reset();
for (const glm::uvec3& coord : GetValidCoords())
OctreeLoader::DeleteCache(GetTreeType(), GetSinglePassTreeDepth(), GetSinglePassTreeFilename(coord));
if (verbose) printf("Cache deleted in %d ms\n", (int)(watch.GetTime() * 1000));
}
}
void StandardOctreeBuilder::TerminateTree()
{
OctreeLoader::WriteCache(mTree, GetTreeType(), GetOutputFile(), GetVerbose());
delete mTree;
}
bool StandardOctreeBuilder::CancelCurPassTree(const glm::uvec3& coord)
{
return OctreeLoader::VerifyCache(GetTreeType(), GetSinglePassTreeDepth(), GetSinglePassTreeFilename(coord));
}
void StandardOctreeBuilder::InitCurPassTree(glm::uvec3 coord)
{
mTree = new Tree<>(GetSinglePassTreeDepth());
}
void StandardOctreeBuilder::FinalizeCurPassTree(glm::uvec3 coord)
{
Stopwatch watch;
if (!mTree->IsEmpty()) // Only append the tree (and compress) if it is not empty
{
// Convert the subtree to a DAG first, this saved time when appending and converting the total tree.
// If it is a single pass tree it needs to be converted anyway :)
// Benchmark (Total build time for subtrees of depth 10, final tree of depth 12, run in Release mode with pool):
// 209.922 seconds without early converting
// 163.645 seconds with early converting
if (verbose) printf("Converting %s to DAG...\n", IsSinglePass() ? "tree" : "subtree");
watch.Reset();
//mCurPassTree->SortNodes();
mTree->ToDAG();
if (verbose) printf("Converting took %d ms.\n", (int)(watch.GetTime() * 1000));
if (!IsSinglePass())
{
if (verbose) printf("Writing subtree to cache...");
watch.Reset();
OctreeLoader::WriteCache(mTree, GetTreeType(), GetSinglePassTreeFilename(coord), verbose);
if (verbose) printf("Wrote cache in %d ms.\n", (int)(watch.GetTime() * 1000));
delete mTree;
mTree = NULL;
}
}
}
void StandardOctreeBuilder::AddNode(const glm::uvec3& coordinate)
{
mTree->AddLeafNode(coordinate);
}
std::vector<size_t> StandardOctreeBuilder::GetOctreeNodesPerLevel()
{
return mTree->GetOctreeNodesPerLevel();
}
std::vector<size_t> StandardOctreeBuilder::GetNodesPerLevel()
{
return mTree->GetNodesPerLevel();
}
std::string StandardOctreeBuilder::GetSinglePassTreeFilename(const glm::uvec3& coord) const
{
char buffer[255];
sprintf(buffer, "%s_%u_(%u_%u_%u)", GetOutputFile().c_str(), GetTreeDepth(), coord.x, coord.y, coord.z);
return std::string(buffer);
}

View File

@@ -0,0 +1,35 @@
#pragma once
#include "BaseStandardOctreeBuilder.h"
#include "../../scene/Octree/Tree.h"
class StandardOctreeBuilder : public BaseStandardOctreeBuilder
{
public:
StandardOctreeBuilder();
~StandardOctreeBuilder() override;
std::string GetTreeType() override;
protected:
void InitTree() override {}
// Finalize the tree
void FinalizeTree() override;
// Step to finalize the main tree (for example storing it to a file)
void TerminateTree() override;
// Cancel the cur pass tree if there's already a cache file available for it
bool CancelCurPassTree(const glm::uvec3& coord) override;
// Initialize the tree for the current pass.
void InitCurPassTree(glm::uvec3 coord) override;
// Terminate the tree in the current pass. This means it should also be appended to the main tree and deleted
void FinalizeCurPassTree(glm::uvec3 coord) override;
// Should add a node to the current pass tree at the given coordinate and color
void AddNode(const glm::uvec3& coordinate) override;
std::vector<size_t> GetOctreeNodesPerLevel() override;
std::vector<size_t> GetNodesPerLevel() override;
private:
std::string GetSinglePassTreeFilename(const glm::uvec3& coord) const;
Tree<>* mTree;
};

View File

@@ -0,0 +1,137 @@
#include "TreeTypeParser.h"
#include "ColorQuantizerFactory.h"
#include "NormalQuantizerFactory.h"
#include "CompressedTextureFactory.h"
#include <regex>
TreeType TreeTypeParser::GetGlobalType(std::string type)
{
char globalTypeChar = type[0];
switch (globalTypeChar)
{
case 'm': return MULTIROOT;
case 'h': return HIERARCHICAL;
case 'o': return ONLYMATERIAL;
case 'u': return UNIQUEINDEX;
case 'r': return RANDOM;
case 'b': return BITTREES;
default: return STANDARD;
}
}
TreeTypeDescriptor TreeTypeParser::GetTreeTypeDescriptor(std::string type)
{
TreeTypeDescriptor res;
std::smatch sm;
res.globalType = GetGlobalType(type);
switch (res.globalType)
{
case ONLYMATERIAL:
{
std::string regexStr = "(o)(c)(" + ColorQuantizerFactory::GetRegexMatcher() + ")?";
std::regex normalMatcher(regexStr);
if (std::regex_match(type, sm, normalMatcher))
{
res.material = sm.str(2);
res.quantizer = sm.str(3);
}
break;
}
case HIERARCHICAL:
{
std::string regexStr = "(h(s?))(c|n|cn|cnr|co)(" + NormalQuantizerFactory::GetRegexMatcher() + "|" + ColorQuantizerFactory::GetRegexMatcher() + ")?";
std::regex normalMatcher(regexStr);
if (std::regex_match(type, sm, normalMatcher))
{
res.additionalTypeInfo = sm.str(2);
res.material = sm.str(3);
res.quantizer = sm.str(4);
}
break;
}
case UNIQUEINDEX:
{
std::string regexStr = "u(s?([0-9]+lod)?)?(" + CompressedTextureFactory<MaterialLibraryPointer>::GetRegexMatcher() + ")?(c|n|cn|cnr|co)(" + NormalQuantizerFactory::GetRegexMatcher() + "|" + ColorQuantizerFactory::GetRegexMatcher() + ")?";
std::regex uniqueIndexMatcher(regexStr);
if (std::regex_match(type, sm, uniqueIndexMatcher))
{
res.additionalTypeInfo = sm.str(1);
res.textureCompressor = sm.str(3);
res.material = sm.str(4);
res.quantizer = sm.str(5);
}
break;
}
case MULTIROOT:
{
std::string regexStr = "m(cc|(([1-8]?)(b[1-8])?))";
std::regex multiRootMatcher(regexStr);
if (std::regex_match(type, sm, multiRootMatcher))
{
res.additionalTypeInfo = sm.str(1);
res.material = "c";
}
break;
}
case BITTREES:
{
std::string regexStr = "blc(" + ColorQuantizerFactory::GetRegexMatcher() + ")?";
std::regex bittreesMatcher(regexStr);
if (std::regex_match(type, sm, bittreesMatcher))
{
res.additionalTypeInfo = "l";
res.material = "c";
res.quantizer = sm.str(1);
}
break;
}
}
return res;
}
unsigned8 TreeTypeParser::GetBitsPerTree(const TreeTypeDescriptor& type)
{
if (type.globalType != MULTIROOT) return 0;
if (type.additionalTypeInfo == "")
// Standard multiroot, one bit per channel
return 1;
if (type.additionalTypeInfo == "cc")
{ // Color Channel per root
return GetBitsPerChannel(type);
}
std::regex multiRootBitMatcher("[0-8]?b([1-8])");
std::smatch sm;
if (std::regex_match(type.additionalTypeInfo, sm, multiRootBitMatcher))
{ // MultiBitMultiRoot tree
return std::stoi(sm.str(1));
}
return 1;
}
unsigned8 TreeTypeParser::GetBitsPerChannel(const TreeTypeDescriptor& type)
{
if (type.globalType != MULTIROOT) return 0;
std::regex multiRootMatcher("([0-8])(b[1-8])?");
std::smatch sm;
if (std::regex_match(type.additionalTypeInfo, sm, multiRootMatcher))
{
return std::stoi(sm.str(1));
}
else
{
return 8;
}
}
unsigned8 TreeTypeParser::GetLevelsWithoutMaterials(const TreeTypeDescriptor& type)
{
if (type.globalType != UNIQUEINDEX) return 0;
std::regex lodMatcher("s?([0-9]+)lod");
std::smatch sm;
unsigned8 lod = 0;
if (std::regex_match(type.additionalTypeInfo, sm, lodMatcher))
lod = std::stoi(sm.str(1));
return lod;
}

View File

@@ -0,0 +1,23 @@
#pragma once
#include "../Defines.h"
#include <string>
struct TreeTypeDescriptor
{
TreeType globalType;
std::string additionalTypeInfo;
std::string textureCompressor;
std::string material;
std::string quantizer;
};
class TreeTypeParser
{
public:
static TreeType GetGlobalType(std::string type);
static TreeTypeDescriptor GetTreeTypeDescriptor(std::string type);
static unsigned8 GetBitsPerTree(const TreeTypeDescriptor& type);
static unsigned8 GetBitsPerChannel(const TreeTypeDescriptor& type);
static unsigned8 GetLevelsWithoutMaterials(const TreeTypeDescriptor& type);
};

View File

@@ -0,0 +1,364 @@
#pragma once
#include "BaseMaterialOctreeBuilder.h"
#include <unordered_set>
#include "../../inc/glm/common.hpp"
#include "../../core/Hashers.h"
#include "../../scene/Material/MaterialLibraryPointer.h"
#include "../../scene/Octree/MaterialLibraryUniqueIndexTree.h"
#include "../../scene/Octree/MaterialTree.h"
template<typename T, typename Comparer>
class UniqueIndexMaterialOctreeBuilder : public BaseMaterialOctreeBuilder<T>
{
private:
static std::string GetSubtreeTextureCompressionType() { return "b"; } // Basic texture compression (e.g. no texture compression)
typedef MaterialLibraryUniqueIndexTree<T, Comparer, T::CHANNELSPERPIXEL> FinalTreeType;
typedef MaterialTree<T, Comparer> IntermediateTreeType;
public:
UniqueIndexMaterialOctreeBuilder(std::string textureCompressionType, BaseQuantizer<T, Comparer>* quantizer = NULL, unsigned32 levelsWithoutMaterials = 0) :
BaseMaterialOctreeBuilder(),
mTree(NULL),
mReduceMaterials(quantizer != NULL),
mTextureCompressionType(textureCompressionType),
mLevelsWithoutMaterials(levelsWithoutMaterials),
mSceneMaterials(std::vector<T>()),
mMaterialReplacers(std::unordered_map<T, T>()),
mCurPreprocessPassMaterials(std::vector<T>()),
mMainTreeMaterials(std::vector<std::pair<glm::uvec3, T>>()),
mIntermediateTree(NULL),
mQuantizer(quantizer)
{}
UniqueIndexMaterialOctreeBuilder(std::string textureCompressionType, unsigned32 levelsWithoutMaterials = 0) :
UniqueIndexMaterialOctreeBuilder(textureCompressionType, NULL, levelsWithoutMaterials)
{}
~UniqueIndexMaterialOctreeBuilder() override
{
if (mIntermediateTree != NULL) delete mIntermediateTree;
if (mTree != NULL) delete mTree;
}
std::string GetTreeType() override
{
return "u" +
(mLevelsWithoutMaterials == 0 ? "" : (std::to_string(mLevelsWithoutMaterials) + "lod"))
+ mTextureCompressionType + MaterialAbbreviation<T>()() +
(mReduceMaterials ? mQuantizer->GetQuantizerDescriptor() : "");
}
std::string GetSubtreeType()
{
return "u" +
(mLevelsWithoutMaterials == 0 ? "" : (std::to_string(mLevelsWithoutMaterials) + "lod"))
+ GetSubtreeTextureCompressionType() + MaterialAbbreviation<T>()() +
(mReduceMaterials ? mQuantizer->GetQuantizerDescriptor() : "");
}
protected:
bool SubTreeCompare(const glm::uvec3& coord1, const glm::uvec3& coord2) const override
{
// Sort them so that the trees with the lowest index will be processed first.
// Since indexes are given in a depth-first order, and the lowest indexes are given to the trees with the highest ChildIndex in each level,
for (unsigned8 bit = GetAppendedTreeLevel(); bit > 0; bit--)
{
unsigned mask = 1 << (bit - 1);
if ((coord1.z & mask) != (coord2.z & mask))
return (coord1.z & mask) > (coord2.z & mask);
if ((coord1.y & mask) != (coord2.y & mask))
return (coord1.y & mask) > (coord2.y & mask);
if ((coord1.x & mask) != (coord2.x & mask))
return (coord1.x & mask) > (coord2.x & mask);
}
return true;
}
// Initialize the main tree
void InitTree() override
{
auto texture = CompressedTextureFactory<MaterialLibraryPointer>::GetCompressedTexture(mTextureCompressionType);
mTree = new FinalTreeType(GetTreeDepth(), texture, mLevelsWithoutMaterials);
IntermediateTreeType* tempTree = new IntermediateTreeType(GetTreeDepth());
if (!IsSinglePass())
{
for (auto coordMaterial : mMainTreeMaterials)
{
tempTree->SetMaterial(coordMaterial.first, GetAppendedTreeLevel(), coordMaterial.second);
}
tempTree->PropagateMaterials(T::WeightedAverage);
mTree->BaseOn(tempTree);
}
mFirstPass = true;
}
bool UsePreprocessing() const override { return !IsSinglePass(); }
void InitPreprocessing() override
{
mSceneMaterials.clear();
mMaterialReplacers.clear();
mMainTreeMaterials.clear();
}
void InitCurPreprocessPass(glm::uvec3 coordinate) override
{
mCurPreprocessPassMaterials.clear();
}
void PreProcessNode(const glm::uvec3& coordinate, const T& color) override { mCurPreprocessPassMaterials.push_back(color); }
void FinalizeCurPreprocessPass(glm::uvec3 coord) override
{
if (mCurPreprocessPassMaterials.empty())
return;
tbb::parallel_sort(mCurPreprocessPassMaterials, Comparer());
std::vector<T> uniqueMaterials;
std::vector<float> uniqueMaterialWeights;
unsigned curMaterialCount = 0;
T lastSeenMaterial = mCurPreprocessPassMaterials[0];
for (auto color : mCurPreprocessPassMaterials)
{
if (!(lastSeenMaterial == color))
{
uniqueMaterials.push_back(lastSeenMaterial);
uniqueMaterialWeights.push_back((float)curMaterialCount);
lastSeenMaterial = color;
curMaterialCount = 0;
}
curMaterialCount++;
}
T avgMaterial = T::WeightedAverage(uniqueMaterials, uniqueMaterialWeights);
mMainTreeMaterials.push_back(std::pair<glm::uvec3, T>(coord, avgMaterial));
// Append the unique colors to the scene colors and compress them to keep the memory usage acceptable
mSceneMaterials.insert(mSceneMaterials.end(), uniqueMaterials.begin(), uniqueMaterials.end());
tbb::parallel_sort(mSceneMaterials, Comparer());
mSceneMaterials.erase(std::unique(mSceneMaterials.begin(), mSceneMaterials.end()), mSceneMaterials.end());
}
void QuantizeSceneMaterials()
{
if (mQuantizer == NULL || !mReduceMaterials) return;
if (verbose) printf("Quantizing/merging %llu %s...", (unsigned64)mSceneMaterials.size(), MaterialName<T>()());
Stopwatch watch; watch.Reset();
auto quantizedSceneMaterials = mQuantizer->QuantizeMaterials(mSceneMaterials);
// Replace the list of scene colors with the quantized scene colors
mSceneMaterials.clear();
for (auto color : *quantizedSceneMaterials)
mSceneMaterials.push_back(color.second);
tbb::parallel_sort(mSceneMaterials, Comparer());
mSceneMaterials.erase(std::unique(mSceneMaterials.begin(), mSceneMaterials.end()), mSceneMaterials.end());
mSceneMaterials.shrink_to_fit();
// Build a dictionary for quick lookup of original scene colors and their quantized counterparts
mMaterialReplacers = std::unordered_map<T, T>();
for (auto color : *quantizedSceneMaterials)
mMaterialReplacers.insert(std::make_pair(color.first, color.second));
// Clear the cur preprocessMaterials (to free up memory during tree construction)
mCurPreprocessPassMaterials = std::vector<T>();
delete quantizedSceneMaterials;
// Replace the old colors by the new ones
if (verbose) printf("Quantized %s in %d ms\n", MaterialName<T>()(), (int)(watch.GetTime() * 1000));
}
void FinalizeTree() override
{
Stopwatch watch;
if (!IsSinglePass())
{
unsigned32 i = 1;
for (const glm::uvec3& coord : GetValidCoords())
{
{ // Scope subTree variable
if (verbose) printf("Reading subtree %u / %u at (%u, %u, %u) from cache...\n", i, (unsigned32)(GetValidCoords().size()), coord.x, coord.y, coord.z);
FinalTreeType* subTree = (FinalTreeType*)OctreeLoader::ReadCache(GetSubtreeType(), GetSinglePassTreeDepth(), GetSinglePassTreeFilename(coord), verbose);
if (subTree != NULL)
{
// Append the subtree to the main tree
if (verbose) printf("Appending subtree... ");;
watch.Reset();
mTree->Append(coord, GetAppendedTreeLevel(), subTree);
delete subTree;
if (verbose) printf("Appending took %d ms.\n", (int)(watch.GetTime() * 1000));
}
}
// Convert the new part of the main tree to a DAG
if (verbose) printf("Converting current tree to DAG...\n");
watch.Reset();
mTree->ToDAG(GetAppendedTreeLevel());
if (verbose) printf("Converting took %d ms.\n", (int)(watch.GetTime() * 1000));
i++;
}
}
// Generate the material texture
watch.Reset();
if (verbose) printf("Generating material texture... ");
mTree->GetMaterialTexture();
if (verbose) printf("Material texture generated in %d ms\n", (int)(watch.GetTime() * 1000));
// Delete the cache files
if (!IsSinglePass())
{
if (verbose) printf("Deleting cache...");
watch.Reset();
for (const glm::uvec3& coord : GetValidCoords())
OctreeLoader::DeleteCache(GetSubtreeType(), GetSinglePassTreeDepth(), GetSinglePassTreeFilename(coord));
if (verbose) printf("Cache deleted in %d ms\n", (int)(watch.GetTime() * 1000));
}
}
// Step to finalize the main tree (for example storing it to a file)
void TerminateTree() override
{
OctreeLoader::WriteCache(mTree, GetTreeType(), GetOutputFile(), verbose);
delete mTree;
mTree = NULL;
mSceneMaterials.clear();
mMaterialReplacers.clear();
mMainTreeMaterials.clear();
}
// Don't build this subtree again if a cache file exists for it
bool CancelCurPassTree(const glm::uvec3& coord) override
{
return OctreeLoader::VerifyCache(GetSubtreeType(), GetSinglePassTreeDepth(), GetSinglePassTreeFilename(coord));
}
// Initialize the tree for the current pass.
void InitCurPassTree(glm::uvec3 coord) override
{
mIntermediateTree = new IntermediateTreeType(GetSinglePassTreeDepth());
mIntermediateTree->UseLeafMap(false);
}
// Terminate the tree in the current pass. This means it should also be appended to the main tree and deleted
void FinalizeCurPassTree(glm::uvec3 coord) override
{
Stopwatch watch;
if (mIntermediateTree->GetNodeCount() > 1) // Only append the tree (and compress) if it is not empty
{
mIntermediateTree->ToDAG();
// Propagate the materials
watch.Reset();
if (verbose) printf("Propagating materials in subtree... ");
mIntermediateTree->PropagateMaterials(T::WeightedAverage);
if (verbose) printf("Materials propagated in %d ms.\n", (int)(watch.GetTime() * 1000));
if (mFirstPass)
{
std::vector<T> uniqueMaterials = mIntermediateTree->GetUniqueMaterials();
mSceneMaterials.insert(mSceneMaterials.end(), uniqueMaterials.begin(), uniqueMaterials.end());
QuantizeSceneMaterials();
mFirstPass = false;
}
// Replace the materials by their quantized counterparts
if (mQuantizer != NULL)
{
if (verbose) printf("Replacing materials by their quantized counterparts.");
watch.Reset();
std::vector<T> curPassMaterials = mIntermediateTree->GetMaterials();
std::vector<T> curPassQuantizedMaterials(curPassMaterials.size());
auto quickQuantizer = dynamic_cast<QuickQuantizer<T>*>(mQuantizer);
if (verbose) printf(".");
// For each material in the curPassMaterials, find the closest material
tbb::parallel_for(size_t(0), curPassMaterials.size(), [&](size_t i)
{
auto cachedReplacer = mMaterialReplacers.find(curPassMaterials[i]);
if (cachedReplacer != mMaterialReplacers.end())
curPassQuantizedMaterials[i] = cachedReplacer->second;
else
{
// If we can use the quick quantizer, try it
if (quickQuantizer != NULL)
{
auto quickQuantizedValue = quickQuantizer->Quantize(curPassMaterials[i]);
auto quickQuantizedCachedReplacer = mMaterialReplacers.find(quickQuantizedValue);
if (quickQuantizedCachedReplacer != mMaterialReplacers.end())
curPassQuantizedMaterials[i] = quickQuantizedCachedReplacer->second;
return;
}
curPassQuantizedMaterials[i] = NearestFinder<T>()(curPassMaterials[i], mSceneMaterials);
}
});
// Update the current scene color map
std::unordered_map<T, T> quantizedMaterials;
for (size_t i = 0; i < curPassMaterials.size(); i++)
quantizedMaterials.insert(std::make_pair(curPassMaterials[i], curPassQuantizedMaterials[i]));
if (verbose) printf(".");
mIntermediateTree->ReplaceMaterials(quantizedMaterials);
if (verbose) printf("Replaced in %d ms.\n", (int)(watch.GetTime() * 1000));
}
// Create the UniqueIndexTree for this current pass
std::string subtreeCompressionType = mTextureCompressionType;
if (!IsSinglePass())
subtreeCompressionType = GetSubtreeTextureCompressionType();
auto texture = CompressedTextureFactory<MaterialLibraryPointer>::GetCompressedTexture(subtreeCompressionType);
auto curPassTree = new FinalTreeType(GetSinglePassTreeDepth(), texture, mLevelsWithoutMaterials);
// Finalize the current pass tree
if (verbose) printf("Finalizing subtree...");
watch.Reset();
curPassTree->BaseOn(mIntermediateTree); // Note that BaseOn will delete the intermediate tree, no need to do that manually
mIntermediateTree = NULL;
if (verbose) printf("Finalized in %d ms.\n", (int)(watch.GetTime() * 1000));
// Convert the subtree to a DAG first, this saved time when appending and converting the total tree
if (verbose) printf("Converting subtree to DAG...\n");
watch.Reset();
curPassTree->ToDAG();
if (verbose) printf("Converting took %d ms.\n", (int)(watch.GetTime() * 1000));
if (IsSinglePass()) // Means we just constructed the root, so no need to append
{
delete mTree;
mTree = curPassTree;
}
else
{
OctreeLoader::WriteCache(curPassTree, GetSubtreeType(), GetSinglePassTreeFilename(coord), verbose);
delete curPassTree;
}
}
else
{
delete mIntermediateTree;
}
}
// Should add a node to the current pass tree at the given coordinate and color
void AddNode(const glm::uvec3& coordinate, const T& color) override { mIntermediateTree->AddLeafNode(coordinate, color); }
void AddMissingNode(const glm::uvec3& coordinate, const T& color) override { if (!mIntermediateTree->HasLeaf(coordinate)) AddNode(coordinate, color); }
std::vector<size_t> GetOctreeNodesPerLevel() override { return mTree->GetOctreeNodesPerLevel(); }
std::vector<size_t> GetNodesPerLevel() override { return mTree->GetNodesPerLevel(); }
private:
std::string GetSinglePassTreeFilename(glm::uvec3 coord)
{
char buffer[255];
sprintf(buffer, "%s_%u_(%u_%u_%u)", GetOutputFile().c_str(), GetTreeDepth(), coord.x, coord.y, coord.z);
return std::string(buffer);
}
FinalTreeType* mTree;
bool mReduceMaterials;
bool mFirstPass;
std::string mTextureCompressionType;
unsigned32 mLevelsWithoutMaterials;
std::vector<T> mSceneMaterials;
std::unordered_map<T, T> mMaterialReplacers;
std::vector<T> mCurPreprocessPassMaterials;
std::vector<std::pair<glm::uvec3, T>> mMainTreeMaterials;
IntermediateTreeType* mIntermediateTree;
BaseQuantizer<T, Comparer>* mQuantizer;
};

View File

@@ -0,0 +1,330 @@
#include "UniqueIndexShiftColoredOctreeBuilder.h"
#include <unordered_map>
#include "OctreeLoader.h"
#include "CompressedTextureFactory.h"
#include "../Hashers.h"
#include "../Comparers.h"
#include "../Util/Stopwatch.h"
#include "../../scene/Octree/MaterialTree.h"
#include "../../scene/Material/Color.h"
#include "../../scene/Material/SignedIntMaterial.h"
#include "../../scene/Material/MaterialQuantizer/ColorQuantizer/BaseColorQuantizer.h"
#include "../../inc/tbb/parallel_sort.h"
#include "../../inc/tbb/concurrent_queue.h"
UniqueIndexShiftColoredOctreeBuilder::UniqueIndexShiftColoredOctreeBuilder(std::string textureCompressionType, BaseQuantizer<Color, ColorCompare>* quantizer, unsigned32 levelsWithoutMaterials) :
BaseMaterialOctreeBuilder(),
mTree(NULL),
mReduceColors(quantizer != NULL),
mTextureCompressionType(textureCompressionType),
mLevelsWithoutMaterials(levelsWithoutMaterials),
mSceneColors(std::vector<Color>()),
mColorReplacers(std::unordered_map<Color, Color>()),
mCurPreprocessPassColors(std::vector<Color>()),
mMainTreeColors(std::vector<std::pair<glm::uvec3, Color>>()),
mIntermediateTree(NULL),
mQuantizer(quantizer)
{}
UniqueIndexShiftColoredOctreeBuilder::~UniqueIndexShiftColoredOctreeBuilder() {}
std::string UniqueIndexShiftColoredOctreeBuilder::GetTreeType() {
return "us" +
(mLevelsWithoutMaterials == 0 ? "" : (std::to_string(mLevelsWithoutMaterials) + "lod"))
+ mTextureCompressionType + "c" +
(mReduceColors ? mQuantizer->GetQuantizerDescriptor() : "");
}
bool UniqueIndexShiftColoredOctreeBuilder::UsePreprocessing() const
{
return !IsSinglePass() || mReduceColors;
}
bool UniqueIndexShiftColoredOctreeBuilder::SubTreeCompare(const glm::uvec3& coord1, const glm::uvec3& coord2) const
{
// Sort them so that the trees with the lowest index will be processed first.
// Since indexes are given in a depth-first order, and the lowest indexes are given to the trees with the highest ChildIndex in each level,
for (unsigned8 bit = GetTreeDepth() - GetSinglePassTreeDepth(); bit > 0; bit--)
{
unsigned mask = 1 << (bit - 1);
if ((coord1.z & mask) != (coord2.z & mask))
return (coord1.z & mask) > (coord2.z & mask);
if ((coord1.y & mask) != (coord2.y & mask))
return (coord1.y & mask) > (coord2.y & mask);
if ((coord1.x & mask) != (coord2.x & mask))
return (coord1.x & mask) > (coord2.x & mask);
}
return true;
}
void UniqueIndexShiftColoredOctreeBuilder::InitTree()
{
auto texture = CompressedTextureFactory<SignedIntMaterial>::GetCompressedTexture(mTextureCompressionType);
mTree = new UniqueIndexShiftTree<Color, ColorCompare>(GetTreeDepth(), texture, mLevelsWithoutMaterials);
if (!IsSinglePass())
{
MaterialTree<Color, ColorCompare>* tempTree = new MaterialTree<Color, ColorCompare>(GetTreeDepth());
mTree->PrepareForMaterials(mSceneColors);
for (auto coordColor : mMainTreeColors)
{
tempTree->SetMaterial(coordColor.first, GetAppendedTreeLevel(), coordColor.second);
}
tempTree->PropagateMaterials(Color::WeightedAverage);
ReplaceByQuantized(tempTree);
mTree->BaseOn(tempTree);
// BaseOn calls delete on tempTree
}
}
void UniqueIndexShiftColoredOctreeBuilder::FinalizeTree()
{
Stopwatch watch;
// Generate the material texture
watch.Reset();
if (verbose) printf("Generating material texture... ");
mTree->GetMaterialTexture();
if (verbose) printf("Material texture generated in %d ms\n", (int)(watch.GetTime() * 1000));
}
void UniqueIndexShiftColoredOctreeBuilder::TerminateTree()
{
OctreeLoader::WriteCache(mTree, GetTreeType(), GetOutputFile(), verbose);
delete mTree;
mSceneColors.clear();
mColorReplacers.clear();
mMainTreeColors.clear();
}
void UniqueIndexShiftColoredOctreeBuilder::InitCurPassTree(glm::uvec3 coord)
{
mIntermediateTree = new MaterialTree<Color, ColorCompare>(GetSinglePassTreeDepth());
//mIntermediateTree->UseLeafMap(true);
}
void UniqueIndexShiftColoredOctreeBuilder::ReplaceByQuantized(MaterialTree<Color, ColorCompare>* tree)
{
std::vector<Color> curPassMaterials = tree->GetUniqueMaterials();
CollectionHelper::Unique(curPassMaterials, ColorCompare());
std::vector<Color> curPassQuantizedMaterials(curPassMaterials.size());
if (verbose) printf(".");
// For each material in the curPassMaterials, find the closest material
tbb::concurrent_queue<size_t> newReplacers;
tbb::parallel_for(size_t(0), curPassMaterials.size(), [&](const size_t& i)
{
auto cachedReplacer = mColorReplacers.find(curPassMaterials[i]);
if (cachedReplacer != mColorReplacers.end())
curPassQuantizedMaterials[i] = cachedReplacer->second;
else
{
curPassQuantizedMaterials[i] = NearestFinder<Color>()(curPassMaterials[i], mSceneColors);
newReplacers.push(i);
}
});
// Add the newly found replacers to the cache
for (auto i = newReplacers.unsafe_begin(); i != newReplacers.unsafe_end(); ++i)
mColorReplacers.insert(std::pair<Color, Color>(curPassMaterials[*i], curPassQuantizedMaterials[*i]));
// Update the current scene color map
std::unordered_map<Color, Color> quantizedColors;
for (size_t i = 0; i < curPassMaterials.size(); i++)
quantizedColors.insert(std::pair<Color, Color>(curPassMaterials[i], curPassQuantizedMaterials[i]));
if (verbose) printf(".");
tree->ReplaceMaterials(quantizedColors);
}
void UniqueIndexShiftColoredOctreeBuilder::FinalizeCurPassTree(glm::uvec3 coord)
{
Stopwatch watch;
if (mIntermediateTree->GetNodeCount() > 1) // Only append the tree (and compress) if it is not empty
{
// Propagate the materials
watch.Reset();
if (verbose) printf("Propagating materials in subtree... ");
mIntermediateTree->PropagateMaterials(Color::WeightedAverage);
if (!IsSinglePass())
{
Color expectedRootColor;
for (auto color : mMainTreeColors)
if (color.first == coord)
{
expectedRootColor = color.second;
break;
}
mIntermediateTree->SetMaterial(glm::uvec3(0), 0, expectedRootColor);
}
if (verbose) printf("Materials propagated in %d ms.\n", (int)(watch.GetTime() * 1000));
// Replace the materials by their quantized counterparts
// This is also necessary
if (mQuantizer != NULL || !IsSinglePass())
{
if (verbose) printf("Replacing materials by their quantized counterparts.");
watch.Reset();
ReplaceByQuantized(mIntermediateTree);
if (verbose) printf("Replaced in %d ms.\n", (int)(watch.GetTime() * 1000));
}
// Create the UniqueIndexTree for this current pass
std::string subtreeCompressionType = mTextureCompressionType;
if (!IsSinglePass()) subtreeCompressionType = "b";
auto texture = CompressedTextureFactory<SignedIntMaterial>::GetCompressedTexture(subtreeCompressionType);
UniqueIndexShiftTree<Color, ColorCompare>* curPassTree = new UniqueIndexShiftTree<Color, ColorCompare>(GetSinglePassTreeDepth(), texture, mLevelsWithoutMaterials);
if (!IsSinglePass())
curPassTree->PrepareForMaterials(mSceneColors);
// Finalize the current pass tree
if (verbose) printf("Finalizing subtree...");
watch.Reset();
curPassTree->BaseOn(mIntermediateTree); // Note that BaseOn will delete the intermediate tree, no need to do that manually
if (verbose) printf("Finalized in %d ms.\n", (int)(watch.GetTime() * 1000));
// Convert the subtree to a DAG first, this saved time (and valueable memory) when appending and converting the total tree
if (verbose) printf("Converting subtree to DAG...\n");
watch.Reset();
curPassTree->ToDAG();
if (verbose) printf("Converting took %d ms.\n", (int)(watch.GetTime() * 1000));
if (IsSinglePass()) // Means we just constructed the root, so no need to append
{
delete mTree;
mTree = curPassTree;
}
else
{
// Append the subtree to the main tree
if (verbose) printf("Appending subtree... ");;
watch.Reset();
mTree->Append(coord, GetAppendedTreeLevel(), curPassTree);
delete curPassTree;
if (verbose) printf("Appending took %d ms.\n", (int)(watch.GetTime() * 1000));
// Convert the new part of the main tree to a DAG
if (verbose) printf("Converting current tree to DAG...\n");
watch.Reset();
mTree->ToDAG(GetAppendedTreeLevel());
if (verbose) printf("Converting took %d ms.\n", (int)(watch.GetTime() * 1000));
}
}
else
{
delete mIntermediateTree;
}
}
void UniqueIndexShiftColoredOctreeBuilder::InitPreprocessing()
{
mSceneColors.clear();
mColorReplacers.clear();
mMainTreeColors.clear();
}
void UniqueIndexShiftColoredOctreeBuilder::InitCurPreprocessPass(glm::uvec3 coordinate)
{
mCurPreprocessPassColors.clear();
}
void UniqueIndexShiftColoredOctreeBuilder::PreProcessNode(const glm::uvec3& coordinate, const Color& color)
{
mCurPreprocessPassColors.push_back(color);
}
void UniqueIndexShiftColoredOctreeBuilder::FinalizeCurPreprocessPass(glm::uvec3 coord)
{
if (mCurPreprocessPassColors.empty())
return;
tbb::parallel_sort(mCurPreprocessPassColors, ColorCompare());
std::vector<Color> uniqueColors;
std::vector<float> uniqueColorWeights;
unsigned curColorCount = 0;
Color lastSeenColor = mCurPreprocessPassColors[0];
for (auto color : mCurPreprocessPassColors)
{
if (!(lastSeenColor == color))
{
uniqueColors.push_back(lastSeenColor);
uniqueColorWeights.push_back((float)curColorCount);
lastSeenColor = color;
}
curColorCount++;
}
Color avgColor = Color::WeightedAverage(uniqueColors, uniqueColorWeights);
mMainTreeColors.push_back(std::pair<glm::uvec3, Color>(coord, avgColor));
// Append the unique colors to the scene colors and compress them to keep the memory usage acceptable
mSceneColors.insert(mSceneColors.end(), uniqueColors.begin(), uniqueColors.end());
tbb::parallel_sort(mSceneColors, ColorCompare());
mSceneColors.erase(std::unique(mSceneColors.begin(), mSceneColors.end()), mSceneColors.end());
}
void UniqueIndexShiftColoredOctreeBuilder::FinalizePreprocessing()
{
// Quantize the scene colors
if (mQuantizer == NULL)
{
if (verbose) printf("Scene contains %llu colors...\n", (unsigned64)mSceneColors.size());
mColorReplacers = std::unordered_map<Color, Color>();
for (auto color : mSceneColors)
mColorReplacers.insert(std::pair<Color, Color>(color, color));
}
else
{
if (verbose) printf("Quantizing/merging %llu colors...", (unsigned64)mSceneColors.size());
Stopwatch watch; watch.Reset();
auto quantizedSceneColors = mQuantizer->QuantizeMaterials(mSceneColors);
// Replace the list of scene colors with the quantized scene colors
mSceneColors.clear();
for (auto color : *quantizedSceneColors)
mSceneColors.push_back(color.second);
tbb::parallel_sort(mSceneColors, ColorCompare());
mSceneColors.erase(std::unique(mSceneColors.begin(), mSceneColors.end()), mSceneColors.end());
mSceneColors.shrink_to_fit();
// Build a dictionary for quick lookup of original scene colors and their quantized counterparts
mColorReplacers = std::unordered_map<Color, Color>();
for (auto color : *quantizedSceneColors)
mColorReplacers.insert(std::pair<Color, Color>(Color(color.first), Color(color.second)));
delete quantizedSceneColors;
// Replace the old colors by the new ones
if (verbose) printf("Quantized colors in %d ms\n", (int)(watch.GetTime() * 1000));
}
// Clear the cur preprocessColors (to free up memory during tree construction)
mCurPreprocessPassColors = std::vector<Color>();
}
void UniqueIndexShiftColoredOctreeBuilder::AddMissingNode(const glm::uvec3& coordinate, const Color& color)
{
if (!mIntermediateTree->HasLeaf(coordinate))
AddNode(coordinate, color);
}
void UniqueIndexShiftColoredOctreeBuilder::AddNode(const glm::uvec3& coordinate, const Color& colorVec)
{
mIntermediateTree->AddLeafNode(coordinate, Color(colorVec));
}
std::vector<size_t> UniqueIndexShiftColoredOctreeBuilder::GetOctreeNodesPerLevel()
{
return mTree->GetOctreeNodesPerLevel();
}
std::vector<size_t> UniqueIndexShiftColoredOctreeBuilder::GetNodesPerLevel()
{
return mTree->GetNodesPerLevel();
}

View File

@@ -0,0 +1,65 @@
#pragma once
#include "BaseMaterialOctreeBuilder.h"
#include <unordered_set>
#include "../../scene/Material/Color.h"
#include "../../inc/glm/common.hpp"
#include "../../core/Hashers.h"
#include "../../scene/Octree/UniqueIndexShiftTree.h"
#include "../../scene/Octree/MaterialTree.h"
#include "../../scene/Material/MaterialQuantizer/BaseQuantizer.h"
struct u8vec3comparer;
struct ColorCompare;
class UniqueIndexShiftColoredOctreeBuilder : public BaseMaterialOctreeBuilder<Color>
{
public:
UniqueIndexShiftColoredOctreeBuilder(std::string textureCompressionType, BaseQuantizer<Color, ColorCompare>* quantizer = NULL, unsigned32 levelsWithoutMaterials = 0);
~UniqueIndexShiftColoredOctreeBuilder() override;
std::string GetTreeType() override;
protected:
bool SubTreeCompare(const glm::uvec3& coord1, const glm::uvec3& coord2) const override;
// Initialize the main tree
void InitTree() override;
bool UsePreprocessing() const override;
void InitPreprocessing() override;
void InitCurPreprocessPass(glm::uvec3 coordinate) override;
void PreProcessNode(const glm::uvec3& coordinate, const Color& color) override;
void FinalizeCurPreprocessPass(glm::uvec3 coord) override;
void FinalizePreprocessing() override;
void FinalizeTree() override;
// Step to finalize the main tree (for example storing it to a file)
void TerminateTree() override;
// Initialize the tree for the current pass.
void InitCurPassTree(glm::uvec3 coord) override;
// Terminate the tree in the current pass. This means it should also be appended to the main tree and deleted
void FinalizeCurPassTree(glm::uvec3 coord) override;
// Should add a node to the current pass tree at the given coordinate and color
void AddNode(const glm::uvec3& coordinate, const Color& color) override;
void AddMissingNode(const glm::uvec3& coordinate, const Color& color) override;
std::vector<size_t> GetOctreeNodesPerLevel() override;
std::vector<size_t> GetNodesPerLevel() override;
void ReplaceByQuantized(MaterialTree<Color, ColorCompare>* intermediateTree);
private:
UniqueIndexShiftTree<Color, ColorCompare>* mTree;
bool mReduceColors;
std::string mTextureCompressionType;
unsigned32 mLevelsWithoutMaterials;
std::vector<Color> mSceneColors;
std::unordered_map<Color, Color> mColorReplacers;
std::vector<Color> mCurPreprocessPassColors;
std::vector<std::pair<glm::uvec3, Color>> mMainTreeColors;
MaterialTree<Color, ColorCompare>* mIntermediateTree;
BaseQuantizer<Color, ColorCompare>* mQuantizer;
};

View File

@@ -0,0 +1,19 @@
#include "PathHelper.h"
#include "Defines.h"
#include <string>
std::string PathHelper::GetExtension(std::string path)
{
return path.substr(path.find_last_of(".") + 1);
}
std::string PathHelper::GetFilename(std::string path)
{
const size_t last_slash_idx = path.find_last_of("\\/");
if (std::string::npos != last_slash_idx)
{
path.erase(0, last_slash_idx + 1);
}
return path;
}

View File

@@ -0,0 +1,10 @@
#pragma once
#include "Defines.h"
#include <string>
namespace PathHelper
{
extern std::string GetExtension(std::string path);
extern std::string GetFilename(std::string path);
};

158
Research/core/Serializer.h Normal file
View File

@@ -0,0 +1,158 @@
#pragma once
#include "Defines.h"
#include <stdio.h>
#include <fstream>
#include <vector>
#include <map>
#include <string>
template<typename T, typename size_type = unsigned32>
struct Serializer
{
static void Serialize(const T& value, std::ostream& out)
{
out.write((char*)&value, sizeof(value));
}
static void Deserialize(T& value, std::istream& in)
{
in.read((char*)&value, sizeof(value));
}
};
template<typename size_type>
struct Serializer<std::string, size_type>
{
static void Serialize(const std::string& value, std::ostream& out)
{
size_type size = (size_type)value.size();
out.write((char*)&size, sizeof(size));
out.write((char*)&value[0], sizeof(char) * size);
}
static void Deserialize(std::string& value, std::istream& in)
{
size_type size;
in.read((char*)&size, sizeof(size));
std::vector<char> res(size);
in.read((char*)&res[0], sizeof(char) * size);
value = std::string(res.begin(), res.end());
}
};
template<typename T, typename size_type>
struct Serializer<std::vector<T>, size_type>
{
static void Serialize(const std::vector<T>& value, std::ostream& out)
{
size_type size = (size_type)value.size();
out.write((char*)&size, sizeof(size));
if (size > 0)
for (size_t i = 0; i < size; i++)
Serializer<T, size_type>::Serialize(value[i], out);
}
static void Deserialize(std::vector<T>& value, std::istream& in)
{
size_type size;
in.read((char*)&size, sizeof(size));
value.resize(size);
if (size > 0)
for (size_t i = 0; i < size; i++)
Serializer<T, size_type>::Deserialize(value[i], in);
}
};
template<typename size_type>
struct Serializer <std::vector<unsigned32>, size_type>
{
static void Serialize(const std::vector<unsigned32>& value, std::ostream& out)
{
size_type size = (size_type)value.size();
out.write((char*)&size, sizeof(size));
if (size > 0)
out.write((char*)&value[0], sizeof(unsigned32) * size);
}
static void Deserialize(std::vector<unsigned32>& value, std::istream& in)
{
size_type size;
in.read((char*)&size, sizeof(size));
value.resize(size);
if (size > 0)
in.read((char*)&value[0], sizeof(unsigned32) * size);
}
};
template<typename size_type>
struct Serializer <std::vector<unsigned8>, size_type>
{
static void Serialize(const std::vector<unsigned8>& value, std::ostream& out)
{
size_type size = (size_type)value.size();
out.write((char*)&size, sizeof(size));
if (size > 0)
out.write((char*)&value[0], sizeof(unsigned8) * size);
}
static void Deserialize(std::vector<unsigned8>& value, std::istream& in)
{
size_type size;
in.read((char*)&size, sizeof(size));
value.resize(size);
if (size > 0)
in.read((char*)&value[0], sizeof(unsigned8) * size);
}
};
template<typename T1, typename T2, typename size_type>
struct Serializer<std::map<T1, T2>, size_type>
{
static void Serialize(const std::map<T1, T2>& map, std::ostream& out)
{
// Write the additional properties to a file
size_type size = (size_type)map.size();
out.write((char*)&size, sizeof(size));
if (size > 0)
for (auto pair : map)
{
Serializer<T1, size_type>::Serialize(pair.first, out);
Serializer<T2, size_type>::Serialize(pair.second, out);
}
}
static void Deserialize(std::map<T1, T2>& map, std::istream& in)
{
map.clear();
size_type size = 0;
in.read((char*)&size, sizeof(size));
if (size > 0)
for (unsigned i = 0; i < size; i++)
{
T1 first;
Serializer<T1>::Deserialize(first, in);
T2 second;
Serializer<T2>::Deserialize(second, in);
map.insert(std::pair<T1, T2>(first, second));
}
}
};
template<typename T>
struct Serializer<T*>
{
static void Serialize(const T* source, size_t count, std::ostream& out)
{
if (count == 0) return;
out.write((char*)source, sizeof(T) * count);
}
static void Deserialize(const T* source, size_t count, std::istream& in)
{
if (count == 0) return;
in.read((char*)source, sizeof(T) * count);
}
};

View File

@@ -0,0 +1,16 @@
#include "StringHelper.h"
#include<algorithm>
bool StringHelper::Replace(std::string& str, const std::string& from, const std::string& to)
{
size_t startPos = str.find(from);
if (startPos == std::string::npos)
return false;
str.replace(startPos, from.length(), to);
return true;
}
void StringHelper::ToUpper(std::string& str)
{
std::transform(str.begin(), str.end(), str.begin(), ::toupper);
}

View File

@@ -0,0 +1,8 @@
#include <string>
class StringHelper
{
public:
static bool Replace(std::string& str, const std::string& toReplace, const std::string& replaceBy);
static void ToUpper(std::string& str);
};

View File

@@ -0,0 +1,490 @@
#pragma once
#include "../Defines.h"
#include "../BitHelper.h"
#include "../CollectionHelper.h"
#include "../Serializer.h"
#include "../../inc/tbb/parallel_for_each.h"
#include "../../inc/tbb/parallel_for.h"
#include <unordered_map>
#include <functional>
#include <iostream>
#include <cassert>
template<typename T>
class BinaryTree
{
private:
template<typename U>
struct BinaryTreeNode
{
private:
BinaryTreeNode<U>* mChildren[2];
BinaryTree<U>* mTree;
T mMaterial;
inline unsigned8 GetChildIndex(size_t coordinate, unsigned8 levelsLeft) const {
return BitHelper::GetLS(coordinate, levelsLeft) ? 1 : 0;
}
inline BinaryTreeNode<U>* GetNodeAt(size_t coordinate, unsigned8 levelsLeft) const
{
return mChildren[GetChildIndex(coordinate, levelsLeft)];
}
public:
BinaryTreeNode(BinaryTree<U>* tree) :
mTree(tree)
{
mChildren[0] = mChildren[1] = NULL;
}
~BinaryTreeNode() {}
BinaryTreeNode* GetChild(unsigned8 index) const
{
assert(index < 2);
return mChildren[index];
}
void SetChild(BinaryTreeNode<U>* child, unsigned8 index) { mChildren[index] = child; }
size_t GetChildCount() const
{
return
(mChildren[0] == NULL ? 0 : 1) +
(mChildren[1] == NULL ? 0 : 1);
}
bool IsLeaf() const { return mChildren[0] == NULL && mChildren[1] == NULL; }
BinaryTreeNode<U>* AddNode(size_t coordinate, unsigned8 levelsLeft)
{
auto node = GetNodeAt(coordinate, levelsLeft);
if (node == NULL)
{
node = mTree->Create();
SetChild(node, GetChildIndex(coordinate, levelsLeft));
}
if (levelsLeft == 0)
return node;
else
return node->AddNode(coordinate, levelsLeft - 1);
}
U GetValueAt(size_t coordinate, unsigned8 levelsLeft) const
{
auto node = GetNodeAt(coordinate, levelsLeft);
if (node == NULL) return GetValue();
if (levelsLeft == 0) return node->GetValue();
return node->GetValueAt(coordinate, levelsLeft - 1);
}
U GetValue() const { return mMaterial; }
void SetValue(const T& material) { mMaterial = material; }
void Traverse(const std::function<void(const BinaryTreeNode<U>*)>& f) const
{
f.operator()(this);
if (mChildren[0] != NULL) mChildren[0]->Traverse(f);
if (mChildren[1] != NULL) mChildren[1]->Traverse(f);
}
static bool Compare(BinaryTreeNode<U>* a, BinaryTreeNode<U>* b)
{
if (a->GetChild(0) != b->GetChild(0)) return (size_t)a->GetChild(0) < (size_t)b->GetChild(0);
if (a->GetChild(1) != b->GetChild(1)) return (size_t)a->GetChild(1) < (size_t)b->GetChild(1);
return a->GetValue() < b->GetValue();
}
static bool Equals(BinaryTreeNode<U>* a, BinaryTreeNode<U>* b)
{
if (a == b) return true;
if (a == NULL || b == NULL) return false;
return a->GetChild(0) == b->GetChild(0) && a->GetChild(1) == b->GetChild(1) && a->GetValue() == b->GetValue();
}
};
unsigned8 mDepth;
BinaryTreeNode<T>* mRoot;
std::vector<BinaryTreeNode<T>*> mNodePool;
std::vector<BinaryTreeNode<T>*> GetNodes()
{
std::vector<BinaryTreeNode<T>*> res;
std::function<void(const BinaryTreeNode<T>*)> nodeFinder = [&](const BinaryTreeNode<T>*) { res.push_back(this); };
mRoot->Traverse(nodeFinder);
CollectionHelper::Unique(res);
return res;
}
void ShiftDown(unsigned8 levels)
{
// Shifts the root down the given number of levels
if (levels == 0) return;
for (unsigned8 i = 0; i < levels; i++)
{
BinaryTreeNode<T>* newRoot = Create();
newRoot->SetChild(mRoot, 0);
BinaryTreeNode<T>* oldRoot = mRoot;
mRoot = newRoot;
mNodePool[0] = newRoot;
mNodePool[mNodePool.size() - 1] = oldRoot;
}
}
static void CalculateNodeLevelsRecursive(BinaryTreeNode<T>* node, unsigned8 level, std::vector<unsigned8>& nodeLevels, const std::unordered_map<BinaryTreeNode<T>*, size_t>& nodeIndices)
{
assert(nodeIndices.find(node) != nodeIndices.end());
auto nodeIndex = nodeIndices.find(node);
nodeLevels[nodeIndex->second] = level;
for (unsigned8 child = 0; child < 2; child++)
{
auto childNode = node->GetChild(child);
if (childNode != NULL)
CalculateNodeLevelsRecursive(childNode, level + 1, nodeLevels, nodeIndices);
}
}
// Calculates the levels of all nodes. Levels are stored in the same order as the node pool.
std::vector<unsigned8> CalculateNodeLevels() const
{
auto nodeIndices = CollectionHelper::GetIndexMap(mNodePool);
std::vector<unsigned8> nodeLevels(mNodePool.size());
CalculateNodeLevelsRecursive(mRoot, 0, nodeLevels, nodeIndices);
return nodeLevels;
}
inline static size_t GetNodePointer(const size_t& index, const size_t& pointerSize, const size_t& valueSize, const size_t& firstLeafIndex, const bool& onlyLeafsContainValues)
{
if (!onlyLeafsContainValues)
return 2 + index * (pointerSize * 2 + valueSize);
else
{
size_t pointer = 2 + std::min(index, firstLeafIndex) * (pointerSize * 2);
if (index > firstLeafIndex)
pointer += (index - firstLeafIndex - 1) * (pointerSize * 2 + valueSize);
return pointer;
}
}
public:
BinaryTree()
{
mDepth = 0;
mRoot = Create();
}
~BinaryTree()
{
tbb::parallel_for_each(mNodePool.begin(), mNodePool.end(), [](BinaryTreeNode<T>* node) { delete node; });
mNodePool.clear();
}
void AddLeafNode(size_t coordinate) { AddNode(coordinate, mDepth); }
void AddNode(size_t coordinate, unsigned8 level)
{
assert(level <= mDepth);
mRoot->AddNode(coordinate, level);
}
T GetValueAtLeaf(size_t coordinate) const { return GetValueAtNode(coordinate, mDepth); }
T GetValueAtNode(size_t coordinate, unsigned8 level) const
{
assert(level <= mDepth);
return mRoot->GetValueAt(coordinate, level);
}
void SetValueAtLeaf(size_t coordinate, T value) { SetValueAtNode(coordinate, mDepth, value); }
void SetValueAtNode(size_t coordinate, unsigned8 level, T value)
{
assert(level <= mDepth);
auto node = mRoot->AddNode(coordinate, level);
node->SetValue(value);
}
BinaryTreeNode<T>* Create()
{
BinaryTreeNode<T>* newNode = new BinaryTreeNode<T>(this);
mNodePool.push_back(newNode);
return newNode;
}
void SetDepth(unsigned8 wantedDepth, bool shiftExisting)
{
if (mDepth != wantedDepth)
{
if (wantedDepth < mDepth)
ShaveUntil(wantedDepth);
else
ShiftDown(wantedDepth - mDepth);
}
mDepth = wantedDepth;
}
// Deletes all nodes of which the level is greater than the given level
void ShaveUntil(unsigned8 level)
{
// Calculate the level for all nodes
std::vector<unsigned8> nodeLevels = CalculateNodeLevels();
for (size_t i = 0; i < mNodePool.size(); i++)
if (nodeLevels[i] > level)
{
delete mNodePool[i];
mNodePool[i] = NULL;
}
else if (nodeLevels[i] == level)
{
// Set all pointers to NULL:
for (unsigned8 child = 0; child < 2; child++) mNodePool[i]->SetChild(NULL, child);
}
mNodePool.erase(std::remove_if(mNodePool.begin(), mNodePool.end(), [](const BinaryTreeNode<T>* node) { return node == NULL; }));
}
void ReplaceValues(const std::unordered_map<T, T>& replacers)
{
tbb::parallel_for(size_t(0), mNodePool.size(), [&](const size_t& i)
{
T curValue = mNodePool[i]->GetValue();
auto replacer = replacers.find(curValue);
if (replacer != replacers.end())
mNodePool[i]->SetValue(replacer->second);
});
}
void Serialize(std::ostream& file) const
{
Serializer<unsigned8>::Serialize(mDepth, file);
// Write the number of nodes in the binary tree:
Serializer<unsigned64>::Serialize((unsigned64)mNodePool.size(), file);
// Write the node materials
for (size_t i = 0; i < mNodePool.size(); i++)
Serializer<T>::Serialize(mNodePool[i]->GetValue(), file);
// Write (consequtively) the child pointers
std::unordered_map<BinaryTreeNode<T>*, size_t> nodeIndices = CollectionHelper::GetIndexMap(mNodePool);
for (size_t i = 0; i < mNodePool.size(); i++)
for (unsigned8 child = 0; child < 2; child++)
{
// Use 0 as NULL pointer, add 1 to all actual pointers
BinaryTreeNode<T>* childNode = mNodePool[i]->GetChild(child);
unsigned64 pointer = 0;
if (childNode != NULL)
{
assert(nodeIndices.find(childNode) != nodeIndices.end());
pointer = nodeIndices[childNode] + 1;
}
Serializer<unsigned64>::Serialize(pointer, file);
}
}
void Deserialize(std::istream& file)
{
if (mNodePool.size() > 1)
{
for (auto node = mNodePool.begin(); node != mNodePool.end(); node++)
delete *node;
mNodePool.resize(1);
}
Serializer<unsigned8>::Deserialize(mDepth, file);
unsigned64 nodeCount;
Serializer<unsigned64>::Deserialize(nodeCount, file);
// The root is always already created, so create nodeCount - 1 nodes:
for (size_t i = 0; i < nodeCount - 1; i++) Create();
// Deserialize the materials for each node
T dummy;
for (size_t i = 0; i < nodeCount; i++)
{
Serializer<T>::Deserialize(dummy, file);
mNodePool[i]->SetValue(dummy);
}
// Create all pointers
for (size_t i = 0; i < mNodePool.size(); i++)
for (unsigned8 child = 0; child < 2; child++)
{
unsigned64 pointer;
Serializer<unsigned64>::Deserialize(pointer, file);
if (pointer != 0)
mNodePool[i]->SetChild(mNodePool[pointer - 1], child);
}
}
// Converts the current binary tree to a DAG, meaning that all duplicate nodes are removed.
void ToDAG()
{
// Fill the current layer with all leaf nodes
std::vector<BinaryTreeNode<T>*> dagNodePool(1, mRoot);
std::vector<BinaryTreeNode<T>*> currentLayer;
std::unordered_set<BinaryTreeNode<T>*> nodesLeft;
std::unordered_map<BinaryTreeNode<T>*, std::vector<BinaryTreeNode<T>*>> parentsMap;
for (auto node : mNodePool)
{
if (node->IsLeaf()) currentLayer.push_back(node);
else
{
nodesLeft.insert(node);
for (unsigned8 child = 0; child < 2; child++)
{
auto childNode = node->GetChild(child);
if (childNode != NULL)
{
auto parent = parentsMap.find(childNode);
if (parent == parentsMap.end())
parentsMap.insert(std::make_pair(childNode, std::vector<BinaryTreeNode<T>*>(1, node)));
else
parent->second.push_back(node);
}
}
}
}
while (!currentLayer.empty() && currentLayer[0] != mRoot)
{
// Find unique nodes and replace them
tbb::parallel_sort(currentLayer.begin(), currentLayer.end(), [](BinaryTreeNode<T>* a, BinaryTreeNode<T>* b) { return BinaryTreeNode<T>::Compare(a, b); });
BinaryTreeNode<T>* cur = NULL;
std::vector<std::pair<BinaryTreeNode<T>*, BinaryTreeNode<T>*>> replacements;
std::vector<BinaryTreeNode<T>*> nextLayer;
size_t uniqueNodes = 0;
for (auto node : currentLayer)
{
if (BinaryTreeNode<T>::Equals(node, cur))
// Make sure that all nodes are replaced by their equals
replacements.push_back(std::make_pair(node, cur));
else
{
uniqueNodes++;
cur = node;
dagNodePool.push_back(cur);
}
auto parents = parentsMap.find(node);
if (parents != parentsMap.end())
nextLayer.insert(nextLayer.end(), parents->second.begin(), parents->second.end());
}
CollectionHelper::Unique(nextLayer, [](BinaryTreeNode<T>* a, BinaryTreeNode<T>* b) { return BinaryTreeNode<T>::Compare(a, b); });
if (uniqueNodes != currentLayer.size())
{
for (auto replacement : replacements)
{
auto toReplace = replacement.first;
auto replacer = replacement.second;
auto parentsIt = parentsMap.find(toReplace);
if (parentsIt == parentsMap.end())
continue;
std::vector<BinaryTreeNode<T>*> parents = parentsIt->second;
for (auto parent : parents)
{
for (unsigned8 child = 0; child < 2; child++)
{
if (parent->GetChild(child) == toReplace)
parent->SetChild(replacer, child);
}
}
delete toReplace;
}
}
currentLayer = nextLayer;
}
mNodePool = dagNodePool;
}
std::vector<unsigned8> Serialize(bool onlyLeafsContainValues) const
{
// The first byte contains the number of bytes per pointer
unsigned8 pointerSize = GetSerializedPointerByteSize(onlyLeafsContainValues);
unsigned8 valueSize = GetMaterialByteSize();
std::vector<unsigned8> res(GetSerializedByteCount(onlyLeafsContainValues), 0);
res[0] = mDepth;
res[1] = pointerSize;
std::vector<BinaryTreeNode<T>*> nodePoolCopy(mNodePool.size());
std::copy(mNodePool.begin(), mNodePool.end(), nodePoolCopy.begin());
size_t firstLeafIndex = ~size_t(0);
if (onlyLeafsContainValues)
{
tbb::parallel_sort(nodePoolCopy.begin() + 1, nodePoolCopy.end(), [](BinaryTreeNode<T>* a, BinaryTreeNode<T>* b)
{
return !(a->IsLeaf()) && (b->IsLeaf());
});
for (size_t i = 0; i < nodePoolCopy.size(); i++)
{
BinaryTreeNode<T>* node = nodePoolCopy[i];
if (node->IsLeaf() && firstLeafIndex > i)
firstLeafIndex = i;
}
}
std::unordered_map<BinaryTreeNode<T>*, size_t> nodeIndices = CollectionHelper::GetIndexMap(nodePoolCopy);
for (size_t i = 0; i < nodePoolCopy.size(); i++)
{
BinaryTreeNode<T>* node = nodePoolCopy[i];
size_t nodePointer = GetNodePointer(i, pointerSize, valueSize, firstLeafIndex, onlyLeafsContainValues);
// Write the node pointers
for (unsigned8 child = 0; child < 2; child++)
{
BinaryTreeNode<T>* childNode = node->GetChild(child);
if (childNode != NULL)
{
assert(nodeIndices.find(childNode) != nodeIndices.end());
size_t childIndex = nodeIndices[childNode];
size_t pointer = GetNodePointer(childIndex, pointerSize, valueSize, firstLeafIndex, onlyLeafsContainValues);
BitHelper::SplitInBytesAndMove(pointer, res, nodePointer + pointerSize * child, pointerSize);
}
}
// Then write the node content/value
if (!onlyLeafsContainValues || node->IsLeaf())
{
std::vector<unsigned8> serializedValue = node->GetValue().Serialize();
std::move(serializedValue.begin(), serializedValue.end(), res.begin() + nodePointer + pointerSize * 2);
}
}
return res;
}
size_t GetNodeCount() const { return mNodePool.size(); }
size_t GetLeafNodeCount() const {
size_t leafNodeCount = 0;
for (auto node : mNodePool) if (node->IsLeaf()) leafNodeCount++;
return leafNodeCount;
}
static size_t GetSerializedByteCount(const size_t& nodeCount, const size_t& leafCount, const size_t& pointerSize, const size_t& valueSize, const bool& onlyLeafsContainValues)
{
return (onlyLeafsContainValues ? leafCount : nodeCount) * valueSize + (2 * pointerSize) * nodeCount;
}
size_t GetSerializedByteCount(bool onlyLeafsContainValues) const
{
return GetSerializedByteCount(GetNodeCount(), GetLeafNodeCount(), GetSerializedPointerByteSize(onlyLeafsContainValues), GetMaterialByteSize(), onlyLeafsContainValues);
}
unsigned8 GetSerializedNodeByteSize(bool onlyLeafsContainValues) const
{
return 2 * GetSerializedPointerByteSize(onlyLeafsContainValues) + GetMaterialByteSize();
}
unsigned8 GetMaterialByteSize() const
{
return sizeof(T);
}
unsigned8 GetSerializedPointerByteSize(bool onlyLeafsContainValues) const
{
// Count the number of leaf nodes:
size_t leafNodeCount = 0;
if (onlyLeafsContainValues)
leafNodeCount = GetLeafNodeCount();
bool fits = false;
unsigned8 pointerSize = 0;
while (!fits)
{
++pointerSize;
size_t requiredBytes = GetSerializedByteCount(GetNodeCount(), leafNodeCount, pointerSize, GetMaterialByteSize(), onlyLeafsContainValues);
fits = BitHelper::Exp2(8 * pointerSize) > requiredBytes;
}
return pointerSize;
}
};

View File

@@ -0,0 +1,223 @@
#pragma once
#include <vector>
#include <array>
#include "IndexIterator.h"
//#include "../BitHelper.h"
template <typename T, unsigned8 BLOCK_POINTER_BITS = 14>
class BlockVector
{
public:
const static unsigned64 BLOCK_SIZE = 1 << BLOCK_POINTER_BITS;
const static size_t BLOCK_SIZE_MASK = BLOCK_SIZE - 1;
protected:
typedef std::vector<T> block;
std::vector<block*> mData;
size_t mSize;
inline size_t block_count(size_t n) const { return (n >> BLOCK_POINTER_BITS) + ((n % BLOCK_SIZE == 0) ? 0 : 1); }
inline size_t block_index(size_t i) const { return i >> BLOCK_POINTER_BITS; }
inline size_t item_index(size_t i) const { return i & BLOCK_SIZE_MASK; }
void shrink_blocks(size_t newBlockCount)
{
// If the size is smaller, delete blocks that are no longer needed.
for (size_t i = newBlockCount; i < mData.size(); i++)
delete mData[i];
}
void init_blocks(size_t oldSize = 0)
{
for (size_t i = oldSize; i < mData.size(); i++)
mData[i] = new block(BLOCK_SIZE);
}
void init_blocks(const T& value, size_t oldSize)
{
for (size_t i = oldSize; i < mData.size(); i++)
mData[i] = new block(BLOCK_SIZE, value);
}
public:
typedef IndexIterator<const BlockVector<T>, const T> const_iterator;
typedef IndexIterator<BlockVector<T>, T> iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
BlockVector() : mData(std::vector<std::array<T, BLOCK_SIZE>*>()), mSize(0) {}
BlockVector(size_t capacity) :
mData(std::vector<block*>()),
mSize(0)
{
reserve(capacity);
}
BlockVector(const BlockVector& r)
{
mData = std::vector<block*>(r.mData.size());
init(0);
for (size_t block = 0; block < r.mData.size(); block++)
std::copy(r.mData[block]->begin(), r.mData[block]->end(), mData[block]->begin());
mSize = r.mSize;
}
BlockVector(BlockVector&& r)
{
mData = std::move(r.mData); r.mData.clear();
mSize = std::move(r.mSize); r.mSize = 0;
}
virtual ~BlockVector()
{
for (block* arr : mData)
{
arr->clear();
delete arr;
}
mData.clear();
}
// Capacity
size_t size() const { return mSize; }
size_t max_size() const { return mData.max_size() * mSize; }
void reserve(size_t n)
{
size_t newBlockCount = block_count(n);
if (mData.size() >= newBlockCount) return; // big enough
size_t oldSize = mData.size();
mData.resize(newBlockCount);
for (size_t i = oldSize; i < mData.size(); i++)
{
mData[i] = new block();
mData[i]->reserve(BLOCK_SIZE);
}
}
// Shrinks the vector so it contains n entries.
void shrink(size_t n)
{
size_t newBlockCount = block_count(n);
shrink_blocks(newBlockCount);
mData.resize(newBlockCount);
mSize = n;
}
void resize(size_t n)
{
size_t oldBlockCount = mData.size();
size_t newBlockCount = block_count(n);
shrink_blocks(newBlockCount);
mData.resize(newBlockCount, NULL);
init_blocks(oldBlockCount);
mSize = n;
}
void resize(size_t n, const T& val)
{
size_t oldBlockCount = mData.size();
size_t newBlockCount = block_count(n);
shrink_blocks(newBlockCount);
mData.resize(newBlockCount, NULL);
init_blocks(val, oldBlockCount);
mSize = n;
}
inline size_t capacity() const { return mData.size() * BLOCK_SIZE; }
inline bool empty() const { return mData.empty(); }
void shrink_to_fit() { resize(mSize); }
// Element access
const T& at(size_t i) const { assert(i < mSize); return mData[block_index(i)]->at(item_index(i)); }
T& at(size_t i) { assert(i < mSize); return mData[block_index(i)]->at(item_index(i)); }
const T& operator[](size_t i) const { return at(i); }
T& operator[](size_t i) { return at(i); }
const T& front() const { return at(0); }
T& front() { return at(0); }
const T& back() const { return at(mSize - 1); }
T& back() { return at(mSize - 1); }
// Modifiers
void push_back(const T& val)
{
// Increase the size if it doesn't fit
if (block_index(mSize) >= mData.size()) reserve(mSize + 1);
// Put the item in the last position
block* b = mData[block_index(mSize)];
size_t itemIndex = item_index(mSize);
if (b->size() == itemIndex) b->push_back(val);
else mData->at(itemIndex) = val;
mSize++;
}
void push_back(T&& val)
{
// Increase the size if it doesn't fit
if (block_index(mSize) >= mData.size()) reserve(mSize + 1);
// Put the item in the last position
block* b = mData[block_index(mSize)];
size_t itemIndex = item_index(mSize);
if (b->size() == itemIndex) b->push_back(val);
else b->at(itemIndex) = val;
mSize++;
}
template <class... Args>
void emplace_back(Args&&... args)
{
size_t blockIndex = block_index(mSize);
if (blockIndex >= mData.size()) reserve(mSize + 1);
block* b = mData[blockIndex];
size_t itemIndex = item_index(mSize);
if (b->size() == itemIndex) b->emplace_back(std::forward<Args>(args)...);
else b->at(itemIndex) = T(std::forward<Args>(args)...);
mSize++;
}
void pop_back() {
mSize--;
}
void clear() {
for (block* block : mData)
delete block;
mData.clear();
mSize = 0;
}
// Iterators
const_iterator begin() const
{
return const_iterator(this, 0);
}
const_iterator end() const
{
return const_iterator(this, mSize);
}
const_reverse_iterator rbegin() const
{
return const_reverse_iterator(end());
}
const_reverse_iterator rend() const
{
return const_reverse_iterator(begin());
}
iterator begin()
{
return iterator(this, 0);
}
iterator end()
{
return iterator(this, mSize);
}
reverse_iterator rbegin()
{
return reverse_iterator(end());
}
reverse_iterator rend()
{
return reverse_iterator(begin());
}
};

View File

@@ -0,0 +1,101 @@
#include "BoolArray.h"
#include "../BitHelper.h"
#include <assert.h>
BoolArray::BoolArray(size_t size, bool value) :
mData(std::vector<unsigned8>(BitHelper::RoundToBytes(size) / 8, value ? 255 : 0)),
mSize(size)
{}
BoolArray::~BoolArray() {}
void BoolArray::Set(const size_t& i, bool value)
{
if (i > mSize) Resize(i + 1);
size_t byteIndex = GetByteIndex(i);
unsigned8 bitIndex = GetBitIndex(i);
unsigned8 bitMask = BitHelper::GetHSSingleBitMask<unsigned8>(bitIndex);
mData[byteIndex] &= ~bitMask;
if (value) mData[byteIndex] |= bitMask;
}
void BoolArray::SetRange(const size_t& start, const size_t& end, bool value)
{
if (end < start) return;
if (end > mSize) Resize(end);
size_t startByteIndex = GetByteIndex(start);
size_t endByteIndex = GetByteIndex(end);
unsigned8 bitMask = BitHelper::GetHSMask<unsigned8>(GetBitIndex(start), 8);
if (startByteIndex == endByteIndex)
bitMask = BitHelper::GetHSMask<unsigned8>(GetBitIndex(start), GetBitIndex(end));
// Set the bits in the first block:
mData[startByteIndex] &= ~bitMask;
if (value) mData[startByteIndex] |= bitMask;
if (startByteIndex == endByteIndex) return; // We're done if only one byte is affected
// Set the bits in all bytes between the start and the end bytes
unsigned8 allSetValue = value ? 0xFF : 0x00;
for (size_t byte = startByteIndex + 1; byte < endByteIndex; byte++)
mData[byte] = allSetValue;
// Set the required bits in the end byte
if (end % 8 != 0)
{
bitMask = BitHelper::GetHSMask<unsigned8>(0, GetBitIndex(end));
mData[endByteIndex] &= ~bitMask;
if (value) mData[endByteIndex] |= bitMask;
}
}
bool BoolArray::Any(const size_t& start, size_t end) const
{
if (end >= mSize) end = mSize - 1;
if (end <= start) return false;
size_t startByteIndex = GetByteIndex(start);
size_t endByteIndex = GetByteIndex(end);
if (startByteIndex == endByteIndex)
return (BitHelper::GetHSMask<unsigned8>(GetBitIndex(start), GetBitIndex(end)) & mData[startByteIndex]) != 0;
// Check the first block
unsigned8 bitMask = BitHelper::GetHSMask<unsigned8>(GetBitIndex(start), 8);
if ((mData[startByteIndex] & bitMask) != 0) return true;
// Check the bytes inbetween
for (size_t byte = startByteIndex + 1; byte < endByteIndex; byte++)
if ((mData[byte] & 0xFF) != 0) return true;
// Check the last bits
return (mData[endByteIndex] & BitHelper::GetHSMask<unsigned8>(0, GetBitIndex(end))) != 0;
}
bool BoolArray::Get(const size_t& i) const
{
assert(i < mSize);
return BitHelper::GetHS(mData[GetByteIndex(i)], GetBitIndex(i));
}
void BoolArray::Resize(const size_t& size)
{
mSize = size;
mData.resize(BitHelper::RoundToBytes(size) / 8);
}
void BoolArray::Clear()
{
mSize = 0;
mData.clear();
mData.shrink_to_fit();
}
void BoolArray::ShrinkToFit()
{
mData.shrink_to_fit();
}
bool BoolArray::operator[](const size_t& i) const
{
return Get(i);
}

View File

@@ -0,0 +1,31 @@
#pragma once
#include "../Defines.h"
#include <vector>
#include <stddef.h>
class BoolArray
{
public:
BoolArray(size_t size, bool value = false);
BoolArray() : BoolArray(0) {}
~BoolArray();
void Set(const size_t& i, bool value);
bool Get(const size_t& i) const;
void SetRange(const size_t& start, const size_t& end, bool value);
bool Any(const size_t& start = 0, size_t end = ~size_t(0)) const;
size_t Size() const { return mSize; }
bool Empty() const { return mSize == 0; }
void Resize(const size_t& size);
void Clear();
void ShrinkToFit();
bool operator[](const size_t& i) const;
private:
static inline size_t GetByteIndex(const size_t& i) { return i >> 3; }
static inline unsigned8 GetBitIndex(const size_t& i) { return i & 0x7; }
size_t mSize;
std::vector<unsigned8> mData;
};

View File

@@ -0,0 +1,187 @@
#pragma once
#include <iterator>
template<typename ContainerT, typename T>
class IndexIterator : public std::iterator<std::random_access_iterator_tag, T>
{
protected:
size_t mIndex;
ContainerT* mContainer;
public:
typedef std::random_access_iterator_tag iterator_category;
typedef
typename iterator<std::random_access_iterator_tag, T>::value_type
value_type;
typedef
typename iterator<std::random_access_iterator_tag, T>::difference_type
difference_type;
typedef
typename iterator<std::random_access_iterator_tag, T>::reference
reference;
typedef
typename iterator<std::random_access_iterator_tag, T>::pointer
pointer;
IndexIterator() : mContainer(NULL), mIndex(0) {}
IndexIterator(ContainerT* container) : mContainer(container), mIndex(0) {}
IndexIterator(ContainerT* container, size_t index) : mContainer(container), mIndex(index) {}
IndexIterator(const IndexIterator<ContainerT, T>& r) : mContainer(r.mContainer), mIndex(r.mIndex) {}
IndexIterator& operator=(const IndexIterator& r)
{
mIndex = r.mIndex; mContainer = r.mContainer; return *this;
}
IndexIterator& operator++() // PREFIX
{
++mIndex; return *this;
}
IndexIterator& operator--() // PREFIX
{
--mIndex; return *this;
}
IndexIterator operator++(int) // POSTFIX
{
return IndexIterator(mContainer, mIndex++);
}
IndexIterator operator--(int) // POSTFIX
{
return IndexIterator(mContainer, mIndex--);
}
IndexIterator operator+(const difference_type& n) const
{
return IndexIterator(mContainer, mIndex + n);
}
IndexIterator& operator+=(const difference_type& n)
{
mIndex += n; return *this;
}
IndexIterator operator-(const difference_type& n) const
{
return IndexIterator(mContainer, mIndex - n);
}
IndexIterator& operator-=(const difference_type& n)
{
mIndex -= n; return *this;
}
reference operator*() const
{
return mContainer->operator[](mIndex);
}
pointer operator->() const
{
return &mContainer->operator[](mIndex);
}
reference operator[](const difference_type& n) const
{
return mContainer->operator[](mIndex + n);
}
template<typename ContainerTypeT, typename TypeT>
friend bool operator==(
const IndexIterator<ContainerTypeT, TypeT>& r1,
const IndexIterator<ContainerTypeT, TypeT>& r2);
template<typename ContainerTypeT, typename TypeT>
friend bool operator!=(
const IndexIterator<ContainerTypeT, TypeT>& r1,
const IndexIterator<ContainerTypeT, TypeT>& r2);
template<typename ContainerTypeT, typename TypeT>
friend bool operator<(
const IndexIterator<ContainerTypeT, TypeT>& r1,
const IndexIterator<ContainerTypeT, TypeT>& r2);
template<typename ContainerTypeT, typename TypeT>
friend bool operator>(
const IndexIterator<ContainerTypeT, TypeT>& r1,
const IndexIterator<ContainerTypeT, TypeT>& r2);
template<typename ContainerTypeT, typename TypeT>
friend bool operator<=(
const IndexIterator<ContainerTypeT, TypeT>& r1,
const IndexIterator<ContainerTypeT, TypeT>& r2);
template<typename ContainerTypeT, typename TypeT>
friend bool operator>=(
const IndexIterator<ContainerTypeT, TypeT>& r1,
const IndexIterator<ContainerTypeT, TypeT>& r2);
template<typename ContainerTypeT, typename TypeT>
friend typename IndexIterator<ContainerTypeT, TypeT>::difference_type operator+(
const IndexIterator<ContainerTypeT, TypeT>& r1,
const IndexIterator<ContainerTypeT, TypeT>& r2);
template<typename ContainerTypeT, typename TypeT>
friend typename IndexIterator<ContainerTypeT, TypeT>::difference_type operator-(
const IndexIterator<ContainerTypeT, TypeT>& r1,
const IndexIterator<ContainerTypeT, TypeT>& r2);
};
template<typename ContainerT, typename T>
bool operator==(const IndexIterator<ContainerT, T>& r1, const IndexIterator<ContainerT, T>& r2)
{
return (r1.mIndex == r2.mIndex && r1.mContainer == r2.mContainer);
}
template<typename ContainerT, typename T>
bool operator!=(const IndexIterator<ContainerT, T>& r1, const IndexIterator<ContainerT, T>& r2)
{
return ((r1.mIndex != r2.mIndex) || (r1.mContainer != r2.mContainer));
}
template<typename ContainerT, typename T>
bool operator<(const IndexIterator<ContainerT, T>& r1, const IndexIterator<ContainerT, T>& r2)
{
if (r1.mContainer != r2.mContainer) return r1.mContainer < r2.mContainer;
return (r1.mIndex < r2.mIndex);
}
template<typename ContainerT, typename T>
bool operator>(const IndexIterator<ContainerT, T>& r1, const IndexIterator<ContainerT, T>& r2)
{
if (r1.mContainer != r2.mContainer) return r1.mContainer > r2.mContainer;
return (r1.mIndex > r2.mIndex);
}
template<typename ContainerT, typename T>
bool operator<=(const IndexIterator<ContainerT, T>& r1, const IndexIterator<ContainerT, T>& r2)
{
if (r1.mContainer != r2.mContainer) return r1.mContainer < r2.mContainer;
return (r1.mIndex <= r2.mIndex);
}
template<typename ContainerT, typename T>
bool operator>=(const IndexIterator<ContainerT, T>& r1, const IndexIterator<ContainerT, T>& r2)
{
if (r1.mContainer != r2.mContainer) return r1.mContainer > r2.mContainer;
return (r1.mIndex >= r2.mIndex);
}
template<typename ContainerT, typename T>
typename IndexIterator<ContainerT, T>::difference_type operator+(
const IndexIterator<ContainerT, T>& r1,
const IndexIterator<ContainerT, T>& r2)
{
assert(r1.mContainer == r2.mContainer);
return r1.mIndex + r2.mIndex;
}
template<typename ContainerT, typename T>
typename IndexIterator<ContainerT, T>::difference_type operator-(
const IndexIterator<ContainerT, T>& r1, const IndexIterator<ContainerT, T>& r2)
{
assert(r1.mContainer == r2.mContainer);
return r1.mIndex - r2.mIndex;
}

View File

@@ -0,0 +1,131 @@
#pragma once
#include <vector>
#include <stack>
#include <algorithm>
#include "../../inc/tbb/parallel_sort.h"
#include "BoolArray.h"
#include "BlockVector.h"
#include "../CollectionHelper.h"
#define USE_BLOCK_VECTOR
// Class for memory efficiency: stores all objects of some type in a vector. Pointers to the object can then be requested.
template<typename T>
class ObjectPool
{
private:
#ifdef USE_BLOCK_VECTOR
BlockVector<T> mData;
#else
std::vector<T> mData;
#endif
BoolArray mMarkedForDeletion;
const size_t mBaseCapacity = 0;
bool AnyMarkedForDeletion() const { return !mMarkedForDeletion.Empty(); }
bool MarkedForDeletion(size_t index) const { return index < mMarkedForDeletion.Size() && mMarkedForDeletion[index]; }
void MarkForDeletion(size_t index)
{
if (index >= mMarkedForDeletion.Size())
mMarkedForDeletion.Resize(index + 1);
mMarkedForDeletion.Set(index, true);
}
public:
ObjectPool(size_t initialCapacity = 1) :
#ifdef USE_BLOCK_VECTOR
mData(BlockVector<T>(initialCapacity)),
#else
mData(std::vector<T>()),
#endif
mMarkedForDeletion(BoolArray()),
mBaseCapacity(initialCapacity)
{
#ifndef USE_BLOCK_VECTOR
mData.reserve(initialCapacity);
#endif
}
// Adds a new item to the pool.
template <class... Args>
T* Create(Args&&... args)
{
//// If any nodes are marked for deletion, reuse their position
//if (!mMarkedForDeletion.empty())
//{
// T* res = &mData[mMarkedForDeletion.top()];
// mMarkedForDeletion.pop();
// return res;
//}
//else // Else, resize the data array to create some space for this new node
//{
mData.emplace_back(std::forward<Args>(args)...);
return &mData[mData.size() - 1];
//}
}
// Moves the node from the given memory position into this pool. Returns the new pointer to this node
T* Add(T* value)
{
mData.emplace_back(std::move(*value));
return &mData[mData.size() - 1];
}
void Delete(size_t i) { MarkForDeletion(i); }
// Removes all nodes that are marked for deletion.
void Clean()
{
// There is only stuff to clean if there are nodes marked for deletion
if (!AnyMarkedForDeletion()) return;
size_t newIdx = 0;
for (size_t oldIdx = 0; oldIdx < mData.size(); oldIdx++)
// If this node should not be deleted, move it to the new position.
if (!MarkedForDeletion(oldIdx))
{
if (oldIdx != newIdx)
mData[newIdx] = std::move(mData[oldIdx]);
//std::swap(mData[newIdx], mData[oldIdx]);
newIdx++;
}
#ifdef USE_BLOCK_VECTOR
mData.shrink(newIdx);
mData.reserve(mBaseCapacity);
#else
mData.erase(mData.begin() + newIdx, mData.end());
mData.shrink_to_fit();
mData.reserve(mBaseCapacity);
#endif
mMarkedForDeletion = BoolArray();
}
void Clear()
{
mData.clear();
mMarkedForDeletion.Clear();
}
template<typename Comparer = std::less<T>>
void Sort(size_t startIdx, size_t endIdx, const Comparer& comparer = Comparer())
{
// Check if any node are deleted in the range that needs to be sorted:
if (AnyMarkedForDeletion() && mMarkedForDeletion.Any(startIdx, endIdx))
Clean();
tbb::parallel_sort(mData.begin() + startIdx, mData.begin() + endIdx, comparer);
}
inline size_t Size() const { return mData.size(); }
inline const T* operator[](size_t i) const
{
if (MarkedForDeletion(i)) return NULL;
return &mData.at(i);
}
inline T* operator[](size_t i)
{
if (MarkedForDeletion(i)) return NULL;
return &mData.at(i);
}
};

119
Research/core/Util/Path.h Normal file
View File

@@ -0,0 +1,119 @@
#pragma once
#include <string>
#include <vector>
#include <fstream>
#include <algorithm>
#include "../Defines.h"
#include "../Serializer.h"
// Path stores a recording detailing any type.
// Interpolator should be a functor with a method specification:
// T operator()(const T& a, const T& b, double time)
// Where a and b should be interpolated between, and time is a value between 0 and 1, indicating the interpolation value
template<typename T, typename Interpolator>
class Path
{
private:
std::vector<T> mFrames;
std::vector<double> mFrameTimes;
public:
Path() : mFrames(std::vector<T>()), mFrameTimes(std::vector<double>()) {}
~Path() {}
void SetStateAtTime(const double& time, const T& state)
{
// Find the position of this new state:
auto pos = std::lower_bound(mFrameTimes.begin(), mFrameTimes.end(), time);
size_t idx = pos - mFrameTimes.begin();
mFrames.insert(mFrames.begin() + idx, state);
mFrameTimes.insert(pos, time);
}
T GetStateAtTime(const double& time) const
{
// Find the frames between which the requested time takes place
size_t afterIdx = std::upper_bound(mFrameTimes.begin(), mFrameTimes.end(), time) - mFrameTimes.begin();
size_t beforeIdx = afterIdx - 1;
if (afterIdx == mFrameTimes.size()) // End of the recording, return the last camera state
return mFrames.back();
if (afterIdx == 0)
return mFrames.front();
// Now linearly interpolate the frames:
double t = ((time - mFrameTimes[beforeIdx]) / (mFrameTimes[afterIdx] - mFrameTimes[beforeIdx]));
const T& before = mFrames[beforeIdx];
const T& after = mFrames[afterIdx];
return Interpolator()(before, after, t);
}
double GetLength() const {
if (Empty()) return 0;
return mFrameTimes.back() - mFrameTimes.front();
}
size_t Size() const { return mFrames.size(); }
/// Removes the camera path node at index i
void RemoveAt(size_t i)
{
mFrames.erase(mFrames.begin() + i);
mFrameTimes.erase(mFrames.begin() + i);
}
/// Removes the last stored camera path node
void RemoveLast()
{
mFrames.pop_back();
mFrameTimes.pop_back();
}
// Makes sure the frametimes go from 0 to the length of the recording
void Normalize()
{
if (Empty()) return;
double offset = mFrameTimes[0];
for (size_t i = 0; i < mFrameTimes.size(); i++)
mFrameTimes[i] = mFrameTimes[i] - offset;
}
bool Empty() const { return mFrames.empty(); }
void Clear()
{
mFrames.clear();
mFrameTimes.clear();
}
void WriteToFile(const std::string& filename)
{
std::ofstream file(filename, std::ios::binary);
unsigned32 recordingLength = (unsigned32)mFrames.size();
Serializer<unsigned32>::Serialize(recordingLength, file);
if (recordingLength > 0)
{
Serializer<T*>::Serialize(&mFrames[0], mFrames.size(), file);
Serializer<double*>::Serialize(&mFrameTimes[0], mFrames.size(), file);
}
file.close();
}
bool ReadFromFile(const std::string& filename)
{
std::ifstream file(filename, std::ios::binary);
if (file.good()) {
unsigned32 recordingLength = 0;
Serializer<unsigned32>::Deserialize(recordingLength, file);
mFrames.resize(recordingLength);
mFrameTimes.resize(recordingLength);
if (recordingLength > 0)
{
Serializer<T*>::Deserialize(&mFrames[0], mFrames.size(), file);
Serializer<double*>::Deserialize(&mFrameTimes[0], mFrames.size(), file);
}
file.close();
return true;
}
return false;
}
};

View File

@@ -0,0 +1,64 @@
#pragma once
#pragma warning(disable:4996)
#include "../Defines.h"
#include <algorithm>
#include <vector>
// Wrapper for standard C array that attempts to minimize memory usage. The user of this class should keep track of the size of the array to correctly be able to insert etc.
template<typename T>
class SmallDynamicArray
{
public:
SmallDynamicArray() : mData(NULL) {}
SmallDynamicArray(size_t size) : mData(new T[size]) {}
SmallDynamicArray(SmallDynamicArray&& source) // Move ctor
{
mData = source.mData;
source.mData = NULL;
}
~SmallDynamicArray() { if (mData != NULL) delete[] mData; }
SmallDynamicArray& operator=(SmallDynamicArray&& source) // Move assignment operator
{
mData = source.mData;
source.mData = NULL;
return *this;
}
inline void Set(const size_t& i, T value) { mData[i] = value; }
inline T& Get(const size_t& i) const { return mData[i]; }
inline T& operator[](const size_t& i) const { return mData[i]; }
inline void SetRange(const T* source, size_t begin, size_t end) { std::copy(source + begin, source + end, mData); }
void Clear() { delete[] mData; mData = NULL; }
inline bool IsEmpty() const { return mData == NULL; }
void Resize(size_t oldSize, const size_t& newSize)
{
T* newData = new T[newSize];
if (!IsEmpty())
{
std::copy(mData, mData + std::min(oldSize, newSize), newData);
delete[] mData;
}
mData = newData;
}
void Insert(size_t index, const T& value, size_t curSize)
{
unsigned* newData = new unsigned[curSize + 1];
// Move the data over to a new array with the correct size
if (mData != NULL)
{
std::copy(mData, mData + index, newData);
std::copy(mData + index, mData + curSize, newData + index + 1);
delete[] mData;
}
newData[index] = value;
mData = newData;
}
private:
T* mData;
};

View File

@@ -0,0 +1,20 @@
#include "Stopwatch.h"
Stopwatch::Stopwatch()
{
Reset();
}
Stopwatch::~Stopwatch()
{
}
void Stopwatch::Reset()
{
begin = clock();
}
double Stopwatch::GetTime()
{
return double(clock() - begin) / CLOCKS_PER_SEC;
}

View File

@@ -0,0 +1,17 @@
#pragma once
#include <ctime>
class Stopwatch
{
public:
Stopwatch();
~Stopwatch();
void Reset();
// Returns the time in seconds
double GetTime();
private:
clock_t begin;
};

View File

@@ -0,0 +1,71 @@
#pragma once
#include "../Defines.h"
#include <vector>
#include <algorithm>
#include "../MathHelper.h"
template<typename T>
class TransferFunction
{
public:
struct Node
{
unsigned32 value;
float opacity;
T material;
Node(unsigned32 value, float opacity, T mat) : value(value), opacity(opacity), material(mat) {}
Node(unsigned32 value) : value(value), opacity(0), material(T()) {}
};
struct NodeCompare { bool operator()(const Node& a, const Node& b) { return a.value < b.value; } };
TransferFunction()
{
}
~TransferFunction() { mFunction.clear(); }
void AddNode(unsigned32 value, float opacity, T mat)
{
Node node(value, opacity, mat);
auto pos = LowerBound(node);
if (pos != mFunction.end() && pos->value == value)
mFunction[pos - mFunction.begin()] = node;
else
mFunction.insert(pos, node);
}
template<typename Interpolator>
void Evaluate(unsigned32 value, float& outOpacity, T& outMat, Interpolator interpolator) const
{
Node node(value);
// Set default values
outOpacity = 1.f;
outMat = T();
// Find the current node
auto pos = LowerBound(node);
if (pos == mFunction.end()) return;
Node after = *pos;
if (pos == mFunction.begin())
{
outOpacity = after.opacity;
outMat = after.material;
return;
}
pos--;
Node before = *pos;
float t = float(value - before.value) / float(after.value - before.value);
outMat = interpolator(before.material, after.material, t);
outOpacity = MathHelper::lerp(t, before.opacity, after.opacity);
}
private:
typename std::vector<Node>::const_iterator LowerBound(const Node& node) const
{
return std::lower_bound(mFunction.begin(), mFunction.end(), node, NodeCompare());
}
std::vector<Node> mFunction;
};

View File

@@ -0,0 +1,29 @@
#pragma once
#include <functional>
#include <vector>
#include "../../inc/glm/glm.hpp"
#include "../Defines.h"
#include "VoxelInfo.h"
class BaseVoxelizer
{
public:
virtual ~BaseVoxelizer() {}
// Should be called before using the octreebuilder. This method initialize the parts of the voxelizer that are not dependent on the scene.
virtual bool Initialize() = 0;
// Loads the scene at the given filename
virtual bool LoadScene(const std::string& filename) = 0;
// Unloads the currently loaded scene (freeing up memory)
virtual bool UnloadScene() = 0;
// Returns all coordinates that should be voxelized at a certain scale.
virtual std::vector<glm::uvec3> GetValidCoords(unsigned8 scale) = 0;
// Voxelizes the currently loaded scene at the given scale. Scale is given as the log_2 of the resolution (e.g. for 1024x1024x1024 use scale = 10).
// Overload can be used to voxelize a certain subsection of the scene.
// For each filled voxel that is found, the node adder is called. The boolean in the nodeadder is
// used as certain voxelizers can give multiple colors for the same voxels. The "best" boolean can then be used to indicate if this is the best color for a voxel.
virtual void Voxelize(unsigned8 scale, unsigned8 partScale, glm::uvec3 partCoord, const std::function<void(const VoxelInfo&, bool best)>& nodeAdder,
bool colors = true, bool normals = true, bool reflectivity = true) = 0;
virtual void Voxelize(unsigned8 scale, const std::function<void(const VoxelInfo&, bool best)>& nodeAdder) { Voxelize(scale, scale, glm::uvec3(0), nodeAdder); }
};

View File

@@ -0,0 +1,227 @@
#include "PVMVoxelizer.h"
#include <algorithm>
#include <numeric>
#include <fstream>
#include "../../PropertyLoader.h"
#include "../OctreeBuilder/SettingsParser.h"
#include "../OctreeBuilder/BaseOctreeBuilder.h"
#include "../../inc/pvm/ddsbase.h"
#include "../../inc/glm/common.hpp"
#include "../ColorHelper.h"
#include "../MathHelper.h"
#include "../StringHelper.h"
#include "../Serializer.h"
#include"../CollectionHelper.h"
struct ColorInterpolator
{
glm::u8vec3 operator()(const glm::u8vec3& color1, glm::u8vec3& color2, float t)
{
//glm::u8vec3 hsv1 = ColorHelper::RGBtoHSV(color1);
//glm::u8vec3 hsv2 = ColorHelper::RGBtoHSV(color2);
//glm::u8vec3 hsvRes;
//hsvRes.r = (unsigned8)MathHelper::lerp(t, (float)hsv1.r, (float)hsv2.r);
//hsvRes.g = (unsigned8)MathHelper::lerp(t, (float)hsv1.g, (float)hsv2.g);
//hsvRes.b = (unsigned8)MathHelper::lerp(t, (float)hsv1.b, (float)hsv2.b);
//return ColorHelper::HSVtoRGB(hsvRes);
return glm::u8vec3(
unsigned8(MathHelper::lerp(t, float(color1.r), float(color2.r))),
unsigned8(MathHelper::lerp(t, float(color1.g), float(color2.g))),
unsigned8(MathHelper::lerp(t, float(color1.b), float(color2.b)))
);
}
};
PVMVoxelizer::PVMVoxelizer() :
mWidth(0), mHeight(0), mDepth(0), mComponents(0), mScale(0), mVolume(std::vector<unsigned8>()), mMinOpacity(0.3f)
{
mTransferFunction = TransferFunction<glm::u8vec3>();
//==============================================
// Bonsai tree TF:
//mTransferFunction.AddNode(0, 0, glm::u8vec3(0));
//mTransferFunction.AddNode(21, 0.f, glm::u8vec3(0, 78, 0));
//mTransferFunction.AddNode(23, 0.7f, glm::u8vec3(0, 78, 0));
//mTransferFunction.AddNode(29, 0.7f, glm::u8vec3(118, 97, 71));
//mTransferFunction.AddNode(255, 1.f, glm::u8vec3(160, 160, 160));
//===============================================
// Baby skull TF:
//mTransferFunction.AddNode(0, 0, glm::u8vec3(0));
//mTransferFunction.AddNode(50, 0.f, glm::u8vec3(255, 0, 0));
//mTransferFunction.AddNode(255, 1.f, glm::u8vec3(160, 160, 160));
//===============================================
// Christmas tree (lossless):
// Weird transfer function to make sure that each value has a unique color
//for (unsigned32 i = 0; i < 256; i++)
//{
// mTransferFunction.AddNode(i * 256, 1.f, glm::u8vec3((i % 2) * 255, (i * 4) % 255, i));
//}
//mTransferFunction.AddNode(0, 0.f, glm::u8vec3(0, 0, 0));
//mTransferFunction.AddNode(4096 * 16, 1.f, glm::u8vec3(255, 255, 255));
// Christmas tree (beautiful)
mTransferFunction.AddNode(0, 0, glm::u8vec3(0));
//mTransferFunction.AddNode(255 * 256, 1.f, glm::u8vec3(255, 255, 255));
mTransferFunction.AddNode(60 * 256, 0.f, glm::u8vec3(0, 50, 0));
mTransferFunction.AddNode(90 * 256, 1.f, glm::u8vec3(0, 50, 0));
mTransferFunction.AddNode(255 * 256, 1.f, glm::u8vec3(255, 255, 0));
//mTransferFunction.AddNode(100 * 256, 1.f, glm::u8vec3(0, 70, 0));
//mTransferFunction.AddNode(130 * 256, 1.f, glm::u8vec3(118, 97, 71));
//mTransferFunction.AddNode(160 * 256, 1.f, glm::u8vec3(255, 255, 0));
//mTransferFunction.AddNode(255 * 256, 1.f, glm::u8vec3(255, 255, 0));
}
PVMVoxelizer::~PVMVoxelizer() {}
bool PVMVoxelizer::Initialize() { return true; }
bool PVMVoxelizer::LoadScene(const std::string& filename)
{
ReadVolumeData(filename, mWidth, mHeight, mDepth, mComponents, mVolume);
mScale = BitHelper::Log2Ceil(std::max(std::max(mWidth, mHeight), mDepth));
// TODO: Error handling
return true;
}
bool PVMVoxelizer::UnloadScene()
{
mWidth = mHeight = mDepth = mComponents = mScale = 0;
mVolume = std::vector<unsigned8>();
return true;
}
std::vector<glm::uvec3> PVMVoxelizer::GetValidCoords(unsigned8 scale)
{
if (scale == 0) return std::vector<glm::uvec3>(1, glm::uvec3(0));
std::vector<glm::uvec3> res;
Voxelize(scale, scale, glm::uvec3(0),
[&](const VoxelInfo& info, bool best) { res.push_back(info.position); },
[](const std::vector<float>& opacities)->float { return *std::max_element(opacities.begin(), opacities.end()); },
[](const std::vector<glm::u8vec3>& colors, const std::vector<float>& opacities)->glm::u8vec3 { return glm::u8vec3(0); });
return res;
}
void PVMVoxelizer::Voxelize(unsigned8 scale, unsigned8 partScale, glm::uvec3 partCoord, const std::function<void(const VoxelInfo&, bool best)>& nodeAdder,
bool colors, bool normals, bool reflectivity)
{
Voxelize(scale, partScale, partCoord, nodeAdder,
[](const std::vector<float>& opacities)->float { return (float)CollectionHelper::CalculateMean(opacities); },
[](const std::vector<glm::u8vec3>& colors, const std::vector<float>& opacities)->glm::u8vec3
{
float totalOpacity = CollectionHelper::Sum(opacities);
glm::vec3 avgColor(0);
for (size_t i = 0; i < colors.size(); i++)
avgColor += glm::vec3(colors[i]) * (opacities[i] / totalOpacity);
return glm::u8vec3((unsigned8)avgColor.x, (unsigned8)avgColor.y, (unsigned8)avgColor.z);
});
}
void PVMVoxelizer::Voxelize(unsigned8 scale, unsigned8 partScale, glm::uvec3 partCoord,
const std::function<void(const VoxelInfo&, bool best)>& nodeAdder,
const std::function<float(const std::vector<float> values)>& opacityFilter,
const std::function<glm::u8vec3(const std::vector<glm::u8vec3>, const std::vector<float>)>& colorFilter)
{
if (scale > mScale)
printf("Warning: volume data at a lower resolution than the requested scale.");
float opacity;
glm::u8vec3 col;
unsigned valueCount = (unsigned32)BitHelper::Exp2(mComponents * 8);
std::vector<float> opacityCache(valueCount);
std::vector<glm::u8vec3> colorCache(valueCount);
for (unsigned i = 0; i < valueCount; i++)
{
mTransferFunction.Evaluate(i, opacity, col, ColorInterpolator());
opacityCache[i] = opacity;
colorCache[i] = col;
}
unsigned32 resolution = (unsigned32)BitHelper::Exp2(partScale);
unsigned32 filterSize = mScale >= partScale ? (unsigned32)BitHelper::Exp2(mScale - partScale) : 1;
unsigned32 maxValue = 0;
unsigned32 filledCells = 0;
for (unsigned32 x = 0; x < resolution; x++)
{
if (x * filterSize >= mWidth) continue;
for (unsigned32 y = 0; y < resolution; y++)
{
if (y * filterSize >= mHeight) continue;
for (unsigned32 z = 0; z < resolution; z++)
{
if (z * filterSize >= mDepth) continue;
if (partScale < mScale)
{
// Call the filter over the values in the scene part that is enclosed by a single voxel
std::vector<float> opacities;
std::vector<glm::u8vec3> colors;
for (unsigned32 volX = x * filterSize; volX < (x + 1) * filterSize; volX++)
for (unsigned32 volY = y * filterSize; volY < (y + 1) * filterSize; volY++)
for (unsigned32 volZ = z * filterSize; volZ < (z + 1) * filterSize; volZ++)
{
size_t volIdx = (volX + volY * mWidth + volZ * (mWidth * mHeight)) * mComponents;
if (volIdx >= mVolume.size()) continue;
unsigned32 value = 0;
BitHelper::JoinBytesLittleEndian(mVolume, value, volIdx, mComponents);
if (value > maxValue) maxValue = value;
colors.push_back(colorCache[value]);
opacities.push_back(opacityCache[value]);
}
opacity = opacityFilter(opacities);
if (opacity > mMinOpacity)
col = colorFilter(colors, opacities);
}
else
{
glm::uvec3 volCoord(
x + partCoord.x * resolution,
y + partCoord.y * resolution,
z + partCoord.z * resolution);
size_t volIdx= (volCoord.x + volCoord.y * mWidth + volCoord.z * (mWidth * mHeight)) * mComponents;
unsigned32 value = 0;
BitHelper::JoinBytesLittleEndian(mVolume, value, volIdx, mComponents);
if (value > maxValue) maxValue = value;
opacity = opacityCache[value];
col = colorCache[value];
}
if (opacity > mMinOpacity)
{
filledCells++;
VoxelInfo info(glm::uvec3(x, z, y), col, glm::vec3(0), 1.f, opacity);
nodeAdder(info, true);
}
}
}
}
printf("Max value: %u, filled: %u / %u (%f %%)\n", maxValue, filledCells, mWidth * mHeight * mDepth, (float(filledCells) / float(mWidth * mHeight * mDepth)) * 100.f);
}
void PVMVoxelizer::ReadVolumeData(const std::string& filename, unsigned32& width, unsigned32& height, unsigned32& depth, unsigned32& components, std::vector<unsigned8>& data)
{
std::string filetype = filename.substr(filename.length() - 3, 3);
StringHelper::ToUpper(filetype);
if (filetype == "PVM")
{
unsigned char* volumeData = readPVMvolume(filename.c_str(), &width, &height, &depth, &components);
data = std::vector<unsigned8>(width * height * depth * components);
for (size_t i = 0; i < data.size(); i++) data[i] = volumeData[i];
delete volumeData;
}
else if (filetype == "DAT")
{
std::ifstream file(filename, std::ios::binary);
unsigned16 width16;
unsigned16 height16;
unsigned16 depth16;
Serializer<unsigned16>::Deserialize(width16, file);
Serializer<unsigned16>::Deserialize(height16, file);
Serializer<unsigned16>::Deserialize(depth16, file);
width = width16;
height = height16;
depth = depth16;
components = 2;
data = std::vector<unsigned8>(width * height * depth * components);
Serializer<unsigned8*>::Deserialize(&data[0], width * height * depth * components, file);
file.close();
}
}

View File

@@ -0,0 +1,46 @@
#pragma once
#ifndef GLM_FORCE_RADIANS
#define GLM_FORCE_RADIANS
#endif
#include <vector>
#include "../../inc/glm/glm.hpp"
#include "../../core/Defines.h"
#include "../Hashers.h"
#include "../Util/TransferFunction.h"
#include "BaseVoxelizer.h"
class PVMVoxelizer : public BaseVoxelizer
{
public:
PVMVoxelizer();
virtual ~PVMVoxelizer() override;
bool Initialize() override;
bool LoadScene(const std::string& sceneFileName) override;
bool UnloadScene() override;
std::vector<glm::uvec3> GetValidCoords(unsigned8 scale) override;
void Voxelize(unsigned8 scale, unsigned8 partScale, glm::uvec3 partCoord, const std::function<void(const VoxelInfo&, bool best)>& nodeAdder,
bool colors = true, bool normals = true, bool reflectivity = true) override;
// Keep other voxelize overloads from the base
using BaseVoxelizer::Voxelize;
protected:
private:
static void ReadVolumeData(const std::string& filename, unsigned32& width, unsigned32& height, unsigned32& depth, unsigned32& components, std::vector<unsigned8>& data);
// Voxelize overload that allows for custom filters. Default is average.
void Voxelize(unsigned8 scale, unsigned8 partScale, glm::uvec3 partCoord,
const std::function<void(const VoxelInfo&, bool best)>& nodeAdder,
const std::function<float(const std::vector<float> values)>& opacityFilter,
const std::function<glm::u8vec3(const std::vector<glm::u8vec3>, const std::vector<float>)>& colorFilter);
unsigned32 mWidth, mHeight, mDepth, mComponents;
unsigned8 mScale;
std::vector<unsigned8> mVolume;
TransferFunction<glm::u8vec3> mTransferFunction;
float mMinOpacity;
};

View File

@@ -0,0 +1,968 @@
#include "TriangleMeshVoxelizer.h"
#include <algorithm>
#include <unordered_set>
// Singletons
#include "../../PropertyLoader.h"
#include "../../shaders/ShaderLoader.h"
// Imports
#include "../../scene/PNG.h"
#include "../../scene/Scene.h"
#include "../../scene/ObjLoader.h"
#include "../Util/Stopwatch.h"
#include "../IntersectTests.h"
#include "../BitHelper.h"
bool TriangleMeshVoxelizer::Initialize() {
if (verbose) printf("Initializing BaseOctreeBuilder... ");
Stopwatch watch;
watch.Reset();
if (!InitializeGLFW())
return false;
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK) {
fprintf(stderr, "Failed to initialize GLEW\n");
return false;
}
if (verbose) printf("Initialization took %d ms \n", (int)(watch.GetTime() * 1000));
return true;
}
bool TriangleMeshVoxelizer::LoadScene(const std::string& sceneFileName)
{
if (verbose) printf("Reading scene \"%s\"... ", sceneFileName.c_str());
Stopwatch watch; watch.Reset();
if (!mObjLoader->Load(sceneFileName.c_str(), mScene)) return false;
if (verbose) printf("Done in %d ms\n", (int)(watch.GetTime() * 1000));
// Prepare OpenGL for rendering
LoadScene(mScene);
LoadShaders(mScene);
// Calculate scene details
CalculateBoundingBox(mScene);
CalculateRootNode();
return true;
}
bool TriangleMeshVoxelizer::UnloadScene()
{
// Clear the texture from memory
for (Mesh mesh : mScene.meshes)
glDeleteTextures(1, &mTextures[mesh.texture]);
// Clear the scene
mScene = Scene();
return true;
}
std::vector<glm::uvec3> TriangleMeshVoxelizer::GetValidCoords(unsigned8 scale)
{
if (scale == 0) return std::vector<glm::uvec3>(1, glm::uvec3(0));
else return CalculateValidSubtrees(scale);
}
void TriangleMeshVoxelizer::Voxelize(unsigned8 scale, unsigned8 partScale, glm::uvec3 partCoord, const std::function<void(const VoxelInfo&, bool best)>& nodeAdder, bool colors, bool normals, bool reflectivity)
{
mReadColors = colors; mReadNormals = normals; mReadReflectivity = reflectivity;
float stepSize = 1.f / (float)BitHelper::Exp2(scale - partScale);
mCurPassRootSize = mRootSize * stepSize;
mCurPassGridSize = (unsigned)(BitHelper::Exp2(partScale));
InitDepthPeel();
DepthPeel(partCoord, nodeAdder);
TerminateDepthPeel();
}
void TriangleMeshVoxelizer::CalculateBoundingBox(Scene& scene)
{
// Left = minX
sceneLeft = (*std::min_element(scene.vertices.begin(), scene.vertices.end(), [](glm::vec3 a, glm::vec3 b) { return a.x < b.x; })).x;
// Right = maxX
sceneRight = (*std::max_element(scene.vertices.begin(), scene.vertices.end(), [](glm::vec3 a, glm::vec3 b) { return a.x < b.x; })).x;
// Bottom = minY
sceneBottom = (*std::min_element(scene.vertices.begin(), scene.vertices.end(), [](glm::vec3 a, glm::vec3 b) { return a.y < b.y; })).y;
// Top = maxY
sceneTop = (*std::max_element(scene.vertices.begin(), scene.vertices.end(), [](glm::vec3 a, glm::vec3 b) { return a.y < b.y; })).y;
// Near = maxZ (OpenGL is weird ;) )
sceneNear = (*std::max_element(scene.vertices.begin(), scene.vertices.end(), [](glm::vec3 a, glm::vec3 b) { return a.z < b.z; })).z;
// Far = minZ (OpenGL is weird ;) )
sceneFar = (*std::min_element(scene.vertices.begin(), scene.vertices.end(), [](glm::vec3 a, glm::vec3 b) { return a.z < b.z; })).z;
float width = sceneRight - sceneLeft;
float height = sceneTop - sceneBottom;
float depth = sceneNear - sceneFar;
float cubesize = std::max(std::max(width, height), depth);
float boundingBoxOffset = cubesize * 0.01f;
sceneLeft -= boundingBoxOffset;
sceneRight += boundingBoxOffset;
sceneBottom -= boundingBoxOffset;
sceneTop += boundingBoxOffset;
sceneNear += boundingBoxOffset;
sceneFar -= boundingBoxOffset;
}
void TriangleMeshVoxelizer::CalculateRootNode()
{
float width = sceneRight - sceneLeft;
float height = sceneTop - sceneBottom;
float depth = sceneNear - sceneFar;
mRootSize = std::max(std::max(width, height), depth);
// Line below centers the scene (but puts it on the bottom)
mRootCenter = glm::vec3(sceneLeft + (width * 0.5f), sceneBottom + (0.5f * mRootSize), sceneFar + (0.5f * depth));
// Line below places the scene on the left bottom far position (optimal for compression).
//mRootCenter = glm::vec3(sceneLeft, sceneBottom, sceneFar) + 0.5f * mRootSize;
//mRootSize *= 1.01f;
}
std::vector<glm::uvec3> TriangleMeshVoxelizer::CalculateValidSubtrees(unsigned8 level)
{
Stopwatch watch; watch.Reset();
if (verbose) printf("Calculating valid subtrees... ");
unsigned steps = 1 << level;
glm::vec3 minPosition = mRootCenter - (mRootSize * 0.5f);
glm::vec3 maxPosition = mRootCenter + (mRootSize * 0.5f);
glm::vec3 cellSize = glm::vec3(mRootSize) / (float)steps;
auto uvec3hasher = [&](glm::uvec3 v) -> std::size_t { return (size_t)(v.x + v.y * steps + v.z * steps * steps); };
std::unordered_set < glm::uvec3, decltype(uvec3hasher)> validCoords(10, uvec3hasher);
// For all triangles in the scene
for (size_t i = 0; i + 2 < mScene.indices.size(); i += 3)
{
unsigned a = mScene.indices[i];
unsigned b = mScene.indices[i + 1];
unsigned c = mScene.indices[i + 2];
glm::vec3 triangle[3] = { mScene.vertices[a], mScene.vertices[b], mScene.vertices[c] };
// Build AABB bounding box around triangle:
glm::vec3 triangleMin = glm::min(glm::min(triangle[0], triangle[1]), triangle[2]);
glm::vec3 triangleMax = glm::max(glm::max(triangle[0], triangle[1]), triangle[2]);
// Process only the cells within this bounding box
glm::vec3 triangleMinCoordsF = glm::floor((triangleMin - minPosition) / cellSize);
glm::uvec3 triangleMinCoords(triangleMinCoordsF.x, triangleMinCoordsF.y, triangleMinCoordsF.z);
glm::vec3 triangleMaxCoordsF = glm::ceil((triangleMax - minPosition) / cellSize);
glm::uvec3 triangleMaxCoords(triangleMaxCoordsF.x, triangleMaxCoordsF.y, triangleMaxCoordsF.z);
// If there is an intersection, add the coord to validCoords
for (unsigned x = triangleMinCoords.x; x < triangleMaxCoords.x; x++)
for (unsigned y = triangleMinCoords.y; y < triangleMaxCoords.y; y++)
for (unsigned z = triangleMinCoords.z; z < triangleMaxCoords.z; z++)
{
glm::vec3 coordF(x, y, z);
glm::vec3 cellMinPosition = minPosition + cellSize * coordF;
glm::vec3 cellMaxPosition = cellMinPosition + cellSize;
if (IntersectTests::BoxTriangleIntersection(cellMinPosition, cellMaxPosition, triangle))
{
validCoords.insert(glm::uvec3(x, y, z));
}
}
}
std::vector<glm::uvec3> res;
for (glm::uvec3 v : validCoords)
res.push_back(v);
if (verbose) printf("Found %llu / %u valid subtrees in %u ms.\n", (unsigned64)validCoords.size(), steps * steps * steps, (unsigned)(watch.GetTime() * 1000));
return res;
}
void TriangleMeshVoxelizer::InitDepthPeel()
{
Stopwatch watch; watch.Reset();
if (verbose) printf("Initializing Depth peeling... ");
depthData = new std::vector<GLfloat>(mCurPassGridSize * mCurPassGridSize);
colorData = new std::vector<GLubyte>(mReadColors ? mCurPassGridSize * mCurPassGridSize * 3 : 0);
normalData = new std::vector<GLfloat>(mReadNormals ? mCurPassGridSize * mCurPassGridSize * 3 : 0);
angleData = new std::vector<GLfloat>(mReadColors && interpolateColors ? mCurPassGridSize * mCurPassGridSize : 0);
reflectivityData = new std::vector<GLfloat>(mReadReflectivity ? mCurPassGridSize * mCurPassGridSize : 0);
// The framebuffer, which regroups 0, 1, or more textures, and 0 or 1 depth buffer.
glGenFramebuffers(1, &mFramebufferName);
glBindFramebuffer(GL_FRAMEBUFFER, mFramebufferName);
// Create a framebuffer texture containing the colors of the current frame
//if (readColors)
//{
glGenTextures(1, &mColorTexture);
glBindTexture(GL_TEXTURE_2D, mColorTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, mCurPassGridSize, mCurPassGridSize, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//}
//if (readNormals)
//{
glGenTextures(1, &mNormalTexture);
glBindTexture(GL_TEXTURE_2D, mNormalTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, mCurPassGridSize, mCurPassGridSize, 0, GL_RGB, GL_FLOAT, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//}
// Create a framebuffer texture containing the angle of the vector pointing to the camera and the normal of the triangle
//if (readColors & interpolateColors)
//{
glGenTextures(1, &mAngleTexture);
glBindTexture(GL_TEXTURE_2D, mAngleTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, mCurPassGridSize, mCurPassGridSize, 0, GL_RED, GL_FLOAT, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//}
glGenTextures(1, &mReflectivityTexture);
glBindTexture(GL_TEXTURE_2D, mReflectivityTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, mCurPassGridSize, mCurPassGridSize, 0, GL_RED, GL_FLOAT, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// Create a first texture to contain a depth map
glGenTextures(1, &mDepthTexture1);
glBindTexture(GL_TEXTURE_2D, mDepthTexture1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, mCurPassGridSize, mCurPassGridSize, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// Create a second texture to contain another depth map
glGenTextures(1, &mDepthTexture2);
glBindTexture(GL_TEXTURE_2D, mDepthTexture2);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, mCurPassGridSize, mCurPassGridSize, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// Build a depthbuffer for correct depth testing in the framebuffer.
glGenRenderbuffers(1, &mDepthRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, mDepthRenderbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, mCurPassGridSize, mCurPassGridSize);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepthRenderbuffer);
// Set "depthTexture" as our GL_DEPTH_ATTACHMENT
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, mDepthTexture1, 0);
//if (readColors)
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mColorTexture, 0);
//if (readColors && interpolateColors)
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, mAngleTexture, 0);
//if (readNormals)
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, mNormalTexture, 0);
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, mReflectivityTexture, 0);
// Set the list of draw buffers.
GLenum DrawBuffers[4] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3 };
glDrawBuffers(4, DrawBuffers); // "3" is the size of DrawBuffers
// Always check that our framebuffer is ok
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
std::cout << "Framebuffer broke. Building the octree failed" << std::endl;
return;
}
// The fullscreen quad's FBO
static const GLfloat g_quad_vertex_buffer_data[] = {
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
-1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
};
glGenBuffers(1, &mQuadVertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, mQuadVertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_quad_vertex_buffer_data), g_quad_vertex_buffer_data, GL_STATIC_DRAW);
mQuadProgram = mShaderLoader->LoadShader("RenderTexture.vert", "RenderTexture.frag");
mImageRenderDepthTexID = glGetUniformLocation(mQuadProgram, "depthTexture");
mImageRenderColorTexID = glGetUniformLocation(mQuadProgram, "renderTexture");
mImageRenderUseDepthID = glGetUniformLocation(mQuadProgram, "showDepth");
if (verbose) printf("Depth peeling initialized in %d ms\n", (int)(watch.GetTime() * 1000));
}
void TriangleMeshVoxelizer::DepthPeel(glm::uvec3 coord, const std::function<void(const VoxelInfo&, bool best)>& nodeAdder) {
mMissingNodes.clear();
glm::vec3 coordF(coord.x, coord.y, coord.z);
mCurPassRootCenter = (mRootCenter - (mRootSize * 0.5f)) + coordF * mCurPassRootSize + mCurPassRootSize * 0.5f;
unsigned frames = 0;
bool done = false;
Direction startDir = Direction::Top;
Direction curDir = startDir;
unsigned lastFrames = frames;
GLuint oldDepthTexture = mDepthTexture2;
GLuint curDepthTexture = mDepthTexture1;
SetDirection(curDir, oldDepthTexture);
Stopwatch mainWatch; mainWatch.Reset();
Stopwatch watch; watch.Reset();
Stopwatch frameWatch; frameWatch.Reset();
do {
if (!pixelsLeft) {
// Print details about the last direction
if (verbose) printf("Processed in %6d ms, %5.2f FPS\n", (int)(watch.GetTime() * 1000), (double)(frames - lastFrames) / watch.GetTime());
watch.Reset(); lastFrames = frames;
// Move to the next direction
unsigned curDirInt = static_cast<unsigned>(curDir);
curDir = static_cast<Direction>(++curDirInt % 3);
// We're done if we processed all directions
if (startDir == curDir)
break;
SetDirection(curDir, oldDepthTexture);
}
frames++;
// ************************************************************************************************************************************ //
// Render to our framebuffer //
// ************************************************************************************************************************************ //
glBindFramebuffer(GL_FRAMEBUFFER, mFramebufferName);
glViewport(0, 0, mCurPassGridSize, mCurPassGridSize); // Render on the whole framebuffer, complete from the lower left corner to the upper right
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, curDepthTexture, 0);
// Clear the screen
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
RenderScene(curDir, oldDepthTexture, (float)mCurPassGridSize, (float)mCurPassGridSize);
// ************************************************************************************************************************************ //
// Render to what the user sees (before processing to improve performance) //
// ************************************************************************************************************************************ //
do
{
// Only render the debug image if the last debug image was drawn more than 1/60th of a second ago
if (manual || frameWatch.GetTime() > 1.0 / 60.0 || frames == 1)
{
frameWatch.Reset();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, mWidth, mHeight); // Render on the whole framebuffer, complete from the lower left corner to the upper right
// Clear the screen
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if (renderScene)
{
RenderScene(curDir, oldDepthTexture, (float)mWidth, (float)mHeight);
}
else
{
RenderDebugImage(curDepthTexture);
}
// Swap buffers
glfwSwapBuffers(mWindow);
glfwPollEvents();
}
} while (manual && glfwGetKey(mWindow, GLFW_KEY_SPACE) != GLFW_PRESS);
// Wait until the user releases the space bar
do { glfwPollEvents(); } while (glfwGetKey(mWindow, GLFW_KEY_SPACE) == GLFW_PRESS);
// ************************************************************************************************************************************ //
// Process the current layer, add all voxels to the tree //
// ************************************************************************************************************************************ //
glBindFramebuffer(GL_FRAMEBUFFER, mFramebufferName);
glReadPixels(startTexX, startTexY, texWidth, texHeight, GL_DEPTH_COMPONENT, GL_FLOAT, &depthData->at(0));
colorTexWidth = BitHelper::CeilToNearestPowerOfTwo(texWidth);
if (mReadColors)
{
glReadBuffer(GL_COLOR_ATTACHMENT0);
// When reading the colors, read the whole image, since something goes wrong with indices that aren't a power of two it seems...
glReadPixels(startTexX, startTexY, colorTexWidth, texHeight, GL_RGB, GL_UNSIGNED_BYTE, &colorData->at(0));
}
if (mReadColors && interpolateColors)
{
glReadBuffer(GL_COLOR_ATTACHMENT1);
glReadPixels(startTexX, startTexY, colorTexWidth, texHeight, GL_RED, GL_FLOAT, &angleData->at(0));
}
if (mReadNormals)
{
glReadBuffer(GL_COLOR_ATTACHMENT2);
glReadPixels(startTexX, startTexY, colorTexWidth, texHeight, GL_RGB, GL_FLOAT, &normalData->at(0));
}
if (mReadReflectivity)
{
glReadBuffer(GL_COLOR_ATTACHMENT3);
glReadPixels(startTexX, startTexY, colorTexWidth, texHeight, GL_RED, GL_FLOAT, &reflectivityData->at(0));
}
SetGridData(curDir, nodeAdder);
// Swap the old and new depthtexture, thus advancing to the next layer
oldDepthTexture = oldDepthTexture == mDepthTexture1 ? mDepthTexture2 : mDepthTexture1;
curDepthTexture = curDepthTexture == mDepthTexture1 ? mDepthTexture2 : mDepthTexture1;
firstPass = false;
} while (glfwGetKey(mWindow, GLFW_KEY_ESCAPE) != GLFW_PRESS && !done);
if (verbose) printf("Adding missing nodes...");
if (mReadColors && interpolateColors)
{
// Add the missing nodes in the current subtree
for (auto node : mMissingNodes)
nodeAdder(node.second, false);
}
if (verbose) printf("Depth peeling took %d ms.\n", (int)(mainWatch.GetTime() * 1000));
}
void TriangleMeshVoxelizer::TerminateDepthPeel()
{
// Cleanup the used resources from GPU
glDeleteFramebuffers(1, &mFramebufferName);
glDeleteRenderbuffers(1, &mDepthRenderbuffer);
glDeleteTextures(1, &mDepthTexture1);
glDeleteTextures(1, &mDepthTexture2);
/*if (readColors)*/ glDeleteTextures(1, &mColorTexture);
/*if (readNormals)*/ glDeleteTextures(1, &mNormalTexture);
glDeleteTextures(1, &mAngleTexture);
glDeleteTextures(1, &mReflectivityTexture);
glDeleteBuffers(1, &mQuadVertexbuffer);
glDeleteProgram(mQuadProgram);
delete depthData;
delete colorData;
delete normalData;
delete angleData;
delete reflectivityData;
}
glm::ivec3 TriangleMeshVoxelizer::WorldToGrid(glm::vec3 world)
{
float halfRootSize = mCurPassRootSize * 0.5f;
float left = mCurPassRootCenter.x - halfRootSize;
float bottom = mCurPassRootCenter.y - halfRootSize;
float far = mCurPassRootCenter.z - halfRootSize;
return glm::ivec3(
((world.x - left) / mCurPassRootSize) * mCurPassGridSize,
((world.y - bottom) / mCurPassRootSize) * mCurPassGridSize,
((world.z - far) / mCurPassRootSize) * mCurPassGridSize);
}
void TriangleMeshVoxelizer::SetDirection(Direction dir, unsigned oldDepthTexture)
{
if (verbose) printf("Processing %s view... ", dir == Top ? "Top " : (dir == Side ? "Side " : "Front"));
float one = 1;
firstPass = true; // First pass in this direction
pixelsLeft = true; // Assume there are at least some pixels in this direction
glClearTexImage(oldDepthTexture, 0, GL_DEPTH_COMPONENT32, GL_FLOAT, &one); // Clear the old depth texture, makes sure we don't use old depth peeling values for a new direction
// Reset AABB for texture read optimalization (based on scene size within octree)
glm::ivec3 lbf = WorldToGrid(glm::vec3(sceneLeft, sceneBottom, sceneFar));
glm::ivec3 rtn = WorldToGrid(glm::vec3(sceneRight, sceneTop, sceneNear));
// Make sure the coordinates are actually on the grid
lbf = glm::clamp(lbf, glm::ivec3(0), glm::ivec3(mCurPassGridSize));
rtn = glm::clamp(rtn, glm::ivec3(0), glm::ivec3(mCurPassGridSize));
texWidth = dir == Side ? rtn.z - lbf.z : rtn.x - lbf.x;
texHeight = dir == Top ? rtn.z - lbf.z : rtn.y - lbf.y;
startTexX = dir == Side ? lbf.z : lbf.x;
startTexY = dir == Top ? mCurPassGridSize - lbf.z - texHeight : lbf.y;
// Make sure we're looking in the right direction
Transform(dir);
}
void TriangleMeshVoxelizer::Transform(Direction dir) {
float halfRootSize = mCurPassRootSize * 0.5f;
// Calculate the edges of the cube in world space
float left = mCurPassRootCenter.x - halfRootSize;
// float right = mCurPassRootCenter.x + halfRootSize;
// float bottom = mCurPassRootCenter.y - halfRootSize;
float top = mCurPassRootCenter.y + halfRootSize;
float near = mCurPassRootCenter.z + halfRootSize;
// float far = mCurPassRootCenter.z - halfRootSize;
glm::vec3 viewPoint = mCurPassRootCenter;
switch (dir)
{
case Side: viewPoint.x = left; break;
case Top: viewPoint.y = top; break;
case Front: viewPoint.z = near; break;
}
glm::mat4 mViewMatrix = glm::lookAt(viewPoint, mCurPassRootCenter, dir == Top ? glm::vec3(0, 0, -1) : glm::vec3(0, 1, 0));
mProjectionMatrix = glm::ortho(-halfRootSize, +halfRootSize, -halfRootSize, +halfRootSize, 0.f, mCurPassRootSize);
mMVP = mProjectionMatrix * mViewMatrix;
}
void TriangleMeshVoxelizer::SetGridData(Direction dir, const std::function<void(const VoxelInfo&, bool best)>& nodeAdder) {
// Check if there are any pixels left
pixelsLeft = false;
unsigned minX = mCurPassGridSize, minY = mCurPassGridSize, maxX = 0, maxY = 0;
glm::u8vec3 color(0);
glm::vec3 normal(0);
float reflectivity = 0.f;
float depth;
float minAngle = 0.25f * sqrtf(2);
// From OpenGL Documentation:
// The data for the ith pixel in the jth row is placed in location j * width + i
for (unsigned j = 0; j < texHeight; j++) // row
for (unsigned i = 0; i < texWidth; i++) // col
{
depth = depthData->at(i + j * texWidth);
if (depth == 1.f)
continue;
pixelsLeft |= true;
unsigned x = i + startTexX;
unsigned y = j + startTexY;
// Find min and max for both directions in the image to determine bounding box for next run.
minX = std::min(minX, x);
minY = std::min(minY, y);
maxX = std::max(maxX, x);
maxY = std::max(maxY, y);
// Get the color of the texel
unsigned texCoord = i + (j * colorTexWidth);
if (mReadColors)
{
unsigned colorTexCoord = (3 * texCoord);
color = glm::u8vec3(colorData->at(colorTexCoord), colorData->at(colorTexCoord + 1), colorData->at(colorTexCoord + 2));
}
if (mReadNormals)
{
unsigned normalTexCoord = (3 * texCoord);
normal = (glm::vec3(normalData->at(normalTexCoord), normalData->at(normalTexCoord + 1), normalData->at(normalTexCoord + 2)) * 2.0f) - 1.0f;
}
if (mReadReflectivity)
{
reflectivity = reflectivityData->at(texCoord);
}
//color = glm::u8vec3(glm::abs(normal) * 255.0f);
// Based on the direction, current location and value of the pixel, mark one of the voxels.
// We're always looking from zero to higher values in the grid
unsigned gridDepth = (unsigned)(depth * (float)mCurPassGridSize);
glm::uvec3 coord;
switch (dir)
{
case Side: coord = glm::uvec3(gridDepth, y, x); break;
case Top: coord = glm::uvec3(x, mCurPassGridSize - gridDepth - 1, mCurPassGridSize - y - 1); break;
case Front: coord = glm::uvec3(x, y, mCurPassGridSize - gridDepth - 1); break;
}
VoxelInfo info(coord, color, normal, 0.f, reflectivity);
if (mReadColors && interpolateColors)
{
info.angle = angleData->at(texCoord);
if (info.angle < minAngle)
{
auto missingNode = mMissingNodes.find(coord);
if (missingNode == mMissingNodes.end())
mMissingNodes.insert(std::make_pair(coord, info));
else if (missingNode->second.angle < info.angle)
missingNode->second = info;
continue;
}
}
nodeAdder(info, true);
}
startTexX = minX;
startTexY = minY;
texWidth = maxX -minX + 1;
texHeight = maxY - minY + 1;
}
void TriangleMeshVoxelizer::LoadScene(Scene& scene)
{
Stopwatch watch;
watch.Reset();
if (verbose) printf("Loading scene... ");
TriangleMeshVoxelizer::Load2DTexture(mMissingTexture, interpolateColors);
for (Mesh mesh : scene.meshes)
{
TriangleMeshVoxelizer::Load2DTexture(mesh.texture, interpolateColors);
}
//glDisable(GL_DEPTH_TEST);
glEnable(GL_DEPTH_TEST);
glCullFace(GL_FRONT_AND_BACK);
// Generate and bind vertex array object
glGenVertexArrays(1, &mVertexArrayID);
glBindVertexArray(mVertexArrayID);
// Generate vertex buffer
glGenBuffers(1, &mVertexBuffer);
glm::vec3 zeroVec(0);
glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
if (!scene.vertices.empty())
glBufferData(GL_ARRAY_BUFFER, scene.vertices.size() * sizeof(glm::vec3), &scene.vertices[0], GL_STATIC_DRAW);
else
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3), &zeroVec, GL_STATIC_DRAW);
// Generate texture coordinate buffer
glGenBuffers(1, &mTextureBuffer);
glBindBuffer(GL_ARRAY_BUFFER, mTextureBuffer);
if (!scene.uvs.empty())
glBufferData(GL_ARRAY_BUFFER, scene.uvs.size() * sizeof(glm::vec2), &scene.uvs[0], GL_STATIC_DRAW);
else
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec2), &zeroVec, GL_STATIC_DRAW);
// Generate the vertex color buffer
glGenBuffers(1, &mVertexColorBuffer);
glBindBuffer(GL_ARRAY_BUFFER, mVertexColorBuffer);
if (!scene.colors.empty())
glBufferData(GL_ARRAY_BUFFER, scene.colors.size() * sizeof(glm::vec3), &scene.colors[0], GL_STATIC_DRAW);
else
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3), &zeroVec, GL_STATIC_DRAW);
// Generate normal buffer
glGenBuffers(1, &mNormalBuffer);
glBindBuffer(GL_ARRAY_BUFFER, mNormalBuffer);
if (!scene.normals.empty())
glBufferData(GL_ARRAY_BUFFER, scene.normals.size() * sizeof(glm::vec3), &scene.normals[0], GL_STATIC_DRAW);
else
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3), &zeroVec, GL_STATIC_DRAW);
// Generate element buffer
glGenBuffers(1, &mElementBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mElementBuffer);
if (!scene.indices.empty())
glBufferData(GL_ELEMENT_ARRAY_BUFFER, scene.indices.size() * sizeof(unsigned), &scene.indices[0], GL_STATIC_DRAW);
if (verbose) printf("Scene loaded in %d ms\n", (int)(watch.GetTime() * 1000));
}
void TriangleMeshVoxelizer::RenderScene(Direction dir, unsigned oldDepthTexture, float viewPortWidth, float viewPortHeight)
{
// Enable the shaders
glUseProgram(mDefaultProgramID);
// Bind old depth texture to texture unit 0
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, oldDepthTexture);
// Tell the fragment shader to use texture unit 0 for the old depth texture
glUniform1i(mOldDepthBufferSampler, 0);
glUniform1i(mFirstPass, firstPass);
glUniform1f(mDepthmargin, 1.0f / (float)mCurPassGridSize); // Half a cell margin
glm::vec3 cameraDir((dir == Side) ? -1.f : 0, (dir == Top) ? -1.f : 0, (dir == Front) ? 1.f : 0);
glUniform3f(mCameraDir, cameraDir.x, cameraDir.y, cameraDir.z);
glProgramUniformMatrix4fv(mDefaultProgramID, mPropertyLoader->GetIntProperty("shader_MVP"), 1, GL_FALSE, &mMVP[0][0]);
// Enable vertex attributes array (positions)
glEnableVertexAttribArray(mPropertyLoader->GetIntProperty("shader_vertexPosition"));
glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
glVertexAttribPointer(
mPropertyLoader->GetIntProperty("shader_vertexPosition"), // Attribute positions
3, // Size
GL_FLOAT, // Type
GL_FALSE, // Normalized
0, // Stride
(void*)0 // Array buffer offset
);
// Enable vertex attributes array (texture coordinates)
glEnableVertexAttribArray(mPropertyLoader->GetIntProperty("shader_vertexUV"));
glBindBuffer(GL_ARRAY_BUFFER, mTextureBuffer);
glVertexAttribPointer(
mPropertyLoader->GetIntProperty("shader_vertexUV"), // Attribute texture coordinates
2, // Size
GL_FLOAT, // Type
GL_FALSE, // Normalized
0, // Stride
(void*)0 // Array buffer offset
);
// Enable vertex attributes array (vertex colors)
glEnableVertexAttribArray(stoi(mPropertyLoader->GetProperty("shader_vertexColor")));
glBindBuffer(GL_ARRAY_BUFFER, mVertexColorBuffer);
glVertexAttribPointer(
stoi(mPropertyLoader->GetProperty("shader_vertexColor")), // Attribute texture coordinates
3, // Size
GL_FLOAT, // Type
GL_FALSE, // Normalized
0, // Stride
(void*)0 // Array buffer offset
);
// Enable vertex attributes array (normals)
glEnableVertexAttribArray(stoi(mPropertyLoader->GetProperty("shader_vertexNormal")));
glBindBuffer(GL_ARRAY_BUFFER, mNormalBuffer);
glVertexAttribPointer(
stoi(mPropertyLoader->GetProperty("shader_vertexNormal")), // Attribute normals
3, // Size
GL_FLOAT, // Type
GL_FALSE, // Normalized
0, // Stride
(void*)0 // Array buffer offset
);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Render meshes
for (Mesh mesh : mScene.meshes) {
// Bind texture to texture unit 1
glActiveTexture(GL_TEXTURE1);
auto loadedTexture = mTextures.find(mesh.texture);
if (loadedTexture == mTextures.end() || mesh.texture == "")
glBindTexture(GL_TEXTURE_2D, mTextures[mMissingTexture]);
else
glBindTexture(GL_TEXTURE_2D, mTextures[mesh.texture]);
// Set texture sampler to texture unit 1
glUniform1i(mTextureSampler, 1);
glUniform1f(mReflectivity, mesh.reflectivity);
// Draw the element arrays
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mElementBuffer);
glDrawElements(
GL_TRIANGLES, // Drawing mode
mesh.size, // Element count
GL_UNSIGNED_INT, // Type
(void*)(mesh.offset * sizeof(unsigned)) // Element array buffer offset
);
}
// Disable vertex attributes arrays
glDisableVertexAttribArray(stoi(mPropertyLoader->GetProperty("shader_vertexPosition")));
glDisableVertexAttribArray(stoi(mPropertyLoader->GetProperty("shader_vertexUV")));
glDisableVertexAttribArray(stoi(mPropertyLoader->GetProperty("shader_vertexNormal")));
}
void TriangleMeshVoxelizer::RenderDebugImage(GLuint depthTexture)
{
// Use our shader
glUseProgram(mQuadProgram);
// Bind our depth texture in Texture Unit 0
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, depthTexture);
// Set our sampler to user Texture Unit 0 for depth texture
glUniform1i(mImageRenderDepthTexID, 0);
// Bind our color texture in Texture Unit 1
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, (!mReadColors && mReadNormals) ? mNormalTexture : mColorTexture);
glUniform1i(mImageRenderColorTexID, 1);
glUniform1i(mImageRenderUseDepthID, !mReadColors && !mReadNormals ? 1 : 0);
// 1rst attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, mQuadVertexbuffer);
glVertexAttribPointer(
0, // attribute 0. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// Draw the triangles !
glDrawArrays(GL_TRIANGLES, 0, 6); // 2*3 indices starting at 0 -> 2 triangles
glDisableVertexAttribArray(0);
}
//************************************
// Returns the index of the texture to access it in the texture vector
//************************************
size_t TriangleMeshVoxelizer::Load2DTexture(std::string filename, bool interpolation) {
if (textureLoaded(filename))
return mTextures[filename];
unsigned textureID;
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
PNG* png = new PNG(filename.c_str());
if (png->Initialized())
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, png->W(), png->H(), 0, GL_RGBA, GL_UNSIGNED_BYTE, png->Data());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
if (interpolation)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
delete png;
glBindTexture(GL_TEXTURE_2D, 0);
mTextures.insert(std::pair<std::string, unsigned>(filename, textureID));
return mTextures.size() - 1;
}
bool TriangleMeshVoxelizer::textureLoaded(std::string filename) {
auto it = mTextures.find(filename);
return it != mTextures.end();
}
void TriangleMeshVoxelizer::ReloadShaders(const Scene& scene) {
glDeleteProgram(mDefaultProgramID);
LoadShaders(scene);
}
void TriangleMeshVoxelizer::LoadShaders(const Scene& scene)
{
Stopwatch watch; watch.Reset();
if (verbose) printf("Loading shaders... ");
std::map<std::string, std::string> additionalProperties;
// TODO: support scenes that contain texture-based and vertex-color based meshes.
if (scene.meshes[0].hasUVs && scene.meshes[0].hasVertexColors)
additionalProperties.insert(std::pair<std::string, std::string>("colorType", "TEXTURE_AND_VERTEX_COLORS"));
else if (scene.meshes[0].hasVertexColors)
additionalProperties.insert(std::pair<std::string, std::string>("colorType", "VERTEX_COLORS"));
else if (scene.meshes[0].hasUVs)
additionalProperties.insert(std::pair<std::string, std::string>("colorType", "TEXTURE_COLORS"));
else
additionalProperties.insert(std::pair<std::string, std::string>("colorType", "NO_COLORS"));
// Initialize and use shader program
mDefaultProgramID = mShaderLoader->LoadShader("DepthPeel.vert", "DepthPeel.frag", additionalProperties);
// Get texture ID
mTextureSampler = glGetUniformLocation(mDefaultProgramID, "textureSampler");
mReflectivity = glGetUniformLocation(mDefaultProgramID, "reflectivity");
mOldDepthBufferSampler = glGetUniformLocation(mDefaultProgramID, "lastDepthMap");
mFirstPass = glGetUniformLocation(mDefaultProgramID, "firstPass");
mDepthmargin = glGetUniformLocation(mDefaultProgramID, "depthMargin");
mCameraDir = glGetUniformLocation(mDefaultProgramID, "cameraDir");
if (verbose) printf("Shaders loaded in %d ms\n", (int)(watch.GetTime() * 1000));
}
TriangleMeshVoxelizer::TriangleMeshVoxelizer() :
depthData(NULL),
colorData(NULL),
normalData(NULL),
angleData(NULL),
mWindow(NULL)
{
ObjLoader::Create();
mObjLoader = ObjLoader::Instance();
ShaderLoader::Create();
mShaderLoader = ShaderLoader::Instance();
//mShaderLoader->SetShaderPath("../Research/shaders/");
PropertyLoader::Create();
mPropertyLoader = PropertyLoader::Instance();
mPropertyLoader->Clear();
mPropertyLoader->AddPropertyFile(std::string("properties.txt"));
mPropertyLoader->AddPropertyFile(std::string("shaders/shader_properties.txt"));
mPropertyLoader->Update();
mWidth = mPropertyLoader->GetIntProperty("octreebuilder_debug_width");
mHeight = mPropertyLoader->GetIntProperty("octreebuilder_debug_height");
manual = mPropertyLoader->GetProperty("octreebuilder_manual") != "0";
renderScene = mPropertyLoader->GetProperty("octreebuilder_renderscene") != "0";
verbose = mPropertyLoader->GetProperty("octreebuilder_verbose") != "0";
interpolateColors = mPropertyLoader->GetProperty("octreebuilder_interpolate_colors") != "0";
useCache = mPropertyLoader->GetProperty("octreebuilder_usecache") != "0";
mMissingTexture = mPropertyLoader->GetProperty("octreebuilder_missing_material");
}
TriangleMeshVoxelizer::~TriangleMeshVoxelizer() {
glDeleteBuffers(1, &mVertexBuffer);
glDeleteBuffers(1, &mTextureBuffer);
glDeleteBuffers(1, &mNormalBuffer);
glDeleteBuffers(1, &mVertexColorBuffer);
glDeleteBuffers(1, &mElementBuffer);
glDeleteProgram(mDefaultProgramID);
std::vector<unsigned> textureIDs;
for (std::map<std::string, unsigned>::iterator it = mTextures.begin(); it != mTextures.end(); ++it) {
textureIDs.push_back(it->second);
}
if (!textureIDs.empty())
glDeleteTextures((GLsizei)textureIDs.size(), &textureIDs[0]);
mTextures.clear();
glDeleteTextures(1, &mTextureSampler);
glDeleteVertexArrays(1, &mVertexArrayID);
glfwTerminate();
ObjLoader::Destroy();
ShaderLoader::Destroy();
PropertyLoader::Destroy();
}
bool TriangleMeshVoxelizer::Reinitialize(bool fullscreen) {
glDeleteBuffers(1, &mVertexBuffer);
glDeleteBuffers(1, &mTextureBuffer);
glDeleteBuffers(1, &mNormalBuffer);
glDeleteBuffers(1, &mElementBuffer);
glDeleteProgram(mDefaultProgramID);
std::vector<unsigned> textureIDs;
for (std::map<std::string, unsigned>::iterator it = mTextures.begin(); it != mTextures.end(); ++it) {
textureIDs.push_back(it->second);
}
glDeleteTextures((GLsizei)textureIDs.size(), &textureIDs[0]);
mTextures.clear();
glDeleteTextures(1, &mTextureSampler);
glDeleteVertexArrays(1, &mVertexArrayID);
glfwTerminate();
return Initialize();
}
bool TriangleMeshVoxelizer::InitializeGLFW() {
// Initialize GLFW
if (!glfwInit()) {
fprintf(stderr, "Failed to initialize GLFW\n");
return false;
}
glfwWindowHint(GLFW_SAMPLES, std::stoi(mPropertyLoader->GetProperty("anti_aliasing")));
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, std::stoi(mPropertyLoader->GetProperty("opengl_version_major")));
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, std::stoi(mPropertyLoader->GetProperty("opengl_version_minor")));
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, 1);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
// Open a window and create OpenGL context
mWindow = glfwCreateWindow(mWidth, mHeight, mPropertyLoader->GetProperty("window_name").c_str(), NULL, NULL);
if (mWindow == NULL) {
fprintf(stderr, "Failed to open GLFW window.\n");
glfwTerminate();
return false;
}
glfwMakeContextCurrent(mWindow);
glfwSetInputMode(mWindow, GLFW_STICKY_KEYS, GL_TRUE);
return true;
}

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