mirror of
https://github.com/mangosfour/server.git
synced 2025-12-13 22:37:03 +00:00
[10097] Update G3D up to v8.0b4
+ Got rid of zip lib requirement in G3D...
Still can re-enable code by defining _HAVE_ZIP...
+ Remove silly X11 lib dependency from G3D
Code doesn't seem to do anything yet anyway, and even if, we don't want it :p
+ Fix another weird G3D build problem...
+ Remove some __asm usage in g3d, which is not available on Win64
My editor also decided to remove a ton of trailing white spaces...tss...
+ Reapply G3D fixes for 64bit VC
+ not use SSE specific header when SSE not enabled in *nix
+ Updated project files
+ New vmap_assembler VC90/VC80 Project
+ vmap assembler binaries updates
NOTE: Old vmap fikes expected work (as tests show) with new library version.
But better use new generated versions. Its different in small parts to bad or good...
(based on Lynx3d's repo commit 44798d3)
Signed-off-by: VladimirMangos <vladimir@getmangos.com>
This commit is contained in:
parent
2f3c518935
commit
ae3ad10bcf
235 changed files with 58189 additions and 4547 deletions
13
contrib/vmap_assembler/VC71/.gitignore
vendored
13
contrib/vmap_assembler/VC71/.gitignore
vendored
|
|
@ -1,13 +0,0 @@
|
|||
#
|
||||
# NOTE! Don't add files that are generated in specific
|
||||
# subdirectories here. Add them in the ".gitignore" file
|
||||
# in that subdirectory instead.
|
||||
#
|
||||
# NOTE! Please use 'git-ls-files -i --exclude-standard'
|
||||
# command after changing this file, to see if there are
|
||||
# any tracked files which get ignored after the change.
|
||||
#
|
||||
# MaNGOS generated files at Windows build
|
||||
#
|
||||
|
||||
*.user
|
||||
|
|
@ -1,322 +0,0 @@
|
|||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.10"
|
||||
Name="vmap_assembler"
|
||||
ProjectGUID="{572FFF74-480C-4472-8ABF-81733BB4049D}"
|
||||
Keyword="Win32Proj">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="..\Debug"
|
||||
IntermediateDirectory="..\Debug\obj"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\..\..\dep\include\g3dlite; ..\..\..\src\shared\vmap"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
||||
MinimalRebuild="TRUE"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="4"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)/vmap_assembler.exe"
|
||||
LinkIncremental="2"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile="$(OutDir)/vmap_assembler.pdb"
|
||||
SubSystem="1"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="..\Release"
|
||||
IntermediateDirectory="..\Release\obj"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="..\..\..\dep\include\g3dlite; ..\..\..\src\shared\vmap"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
||||
RuntimeLibrary="0"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="3"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)/vmap_assembler.exe"
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="TRUE"
|
||||
SubSystem="1"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
|
||||
<File
|
||||
RelativePath=".\..\vmap_assembler.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="vmaplib">
|
||||
<File
|
||||
RelativePath="..\..\..\src\shared\vmap\AABSPTree.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\shared\vmap\BaseModel.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\shared\vmap\BaseModel.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\shared\vmap\CoordModelMapping.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\shared\vmap\CoordModelMapping.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\shared\vmap\DebugCmdLogger.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\shared\vmap\DebugCmdLogger.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\shared\vmap\ManagedModelContainer.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\shared\vmap\ManagedModelContainer.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\shared\vmap\ModelContainer.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\shared\vmap\ModelContainer.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\shared\vmap\NodeValueAccess.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\shared\vmap\ShortBox.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\shared\vmap\ShortVector.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\shared\vmap\SubModel.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\shared\vmap\SubModel.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\shared\vmap\TileAssembler.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\shared\vmap\TileAssembler.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\shared\vmap\TreeNode.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\shared\vmap\TreeNode.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\shared\vmap\VMapTools.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="g3dlite">
|
||||
<File
|
||||
RelativePath="..\..\..\dep\src\g3dlite\AABox.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\AABox.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\AABSPTree.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Array.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\src\g3dlite\Box.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Box.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\CollisionDetection.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\CoordinateFrame.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\src\g3dlite\Crypto.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Crypto.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\debug.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\src\g3dlite\format.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\format.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\g3dmath.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\g3dmath.inl">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\GCamera.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Line.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\src\g3dlite\Matrix3.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Matrix3.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\src\g3dlite\Plane.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Plane.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\platform.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Quat.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Quat.inl">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Ray.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\RegistryUtil.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Sphere.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\stringutils.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\src\g3dlite\System.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\System.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Table.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\src\g3dlite\Triangle.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Triangle.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Vector2.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Vector2.inl">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Vector2int16.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\src\g3dlite\Vector3.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Vector3.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Vector3.inl">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Vector3int16.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\src\g3dlite\Vector4.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Vector4.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Vector4.inl">
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
|
|
@ -44,7 +44,7 @@
|
|||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
RuntimeLibrary="3"
|
||||
EnableEnhancedInstructionSet="1"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
|
|
@ -121,7 +121,7 @@
|
|||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="..\..\..\dep\include\g3dlite;..\..\..\src\shared\vmap;"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
||||
RuntimeLibrary="0"
|
||||
RuntimeLibrary="2"
|
||||
EnableEnhancedInstructionSet="1"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
|
|
@ -274,182 +274,6 @@
|
|||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="g3dlite"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\src\g3dlite\AABox.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\AABox.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\AABSPTree.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Array.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\src\g3dlite\Box.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Box.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\CollisionDetection.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\CoordinateFrame.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\src\g3dlite\Crypto.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Crypto.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\debug.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\src\g3dlite\format.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\format.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\g3dmath.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\g3dmath.inl"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\GCamera.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Line.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\src\g3dlite\Matrix3.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Matrix3.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\src\g3dlite\Plane.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Plane.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\platform.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Quat.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Quat.inl"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Ray.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\RegistryUtil.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Sphere.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\stringutils.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\src\g3dlite\System.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\System.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Table.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\src\g3dlite\Triangle.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Triangle.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Vector2.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Vector2.inl"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Vector2int16.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\src\g3dlite\Vector3.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Vector3.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Vector3.inl"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Vector3int16.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\src\g3dlite\Vector4.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Vector4.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Vector4.inl"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9,00"
|
||||
Version="9.00"
|
||||
Name="vmap_assembler"
|
||||
ProjectGUID="{572FFF74-480C-4472-8ABF-81733BB4049D}"
|
||||
Keyword="Win32Proj"
|
||||
|
|
@ -45,7 +45,7 @@
|
|||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
RuntimeLibrary="3"
|
||||
EnableEnhancedInstructionSet="1"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
|
|
@ -119,9 +119,9 @@
|
|||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="..\..\..\dep\include\g3dlite;..\..\..\src\shared\vmap;"
|
||||
AdditionalIncludeDirectories="..\..\..\dep\include\g3dlite;..\..\..\src\shared\vmap;..\..\..\src\framework;..\..\..\dep\ACE_wrappers"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
||||
RuntimeLibrary="0"
|
||||
RuntimeLibrary="2"
|
||||
EnableEnhancedInstructionSet="1"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
|
|
@ -273,182 +273,6 @@
|
|||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="g3dlite"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\src\g3dlite\AABox.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\AABox.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\AABSPTree.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Array.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\src\g3dlite\Box.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Box.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\CollisionDetection.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\CoordinateFrame.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\src\g3dlite\Crypto.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Crypto.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\debug.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\src\g3dlite\format.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\format.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\g3dmath.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\g3dmath.inl"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\GCamera.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Line.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\src\g3dlite\Matrix3.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Matrix3.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\src\g3dlite\Plane.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Plane.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\platform.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Quat.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Quat.inl"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Ray.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\RegistryUtil.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Sphere.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\stringutils.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\src\g3dlite\System.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\System.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Table.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\src\g3dlite\Triangle.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Triangle.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Vector2.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Vector2.inl"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Vector2int16.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\src\g3dlite\Vector3.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Vector3.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Vector3.inl"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Vector3int16.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\src\g3dlite\Vector4.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Vector4.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\dep\include\g3dlite\G3D\Vector4.inl"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
|
|
|
|||
|
|
@ -1,23 +0,0 @@
|
|||
Microsoft Visual Studio Solution File, Format Version 8.00
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vmap_assembler", "VC71\vmap_assembler.vcproj", "{572FFF74-480C-4472-8ABF-81733BB4049D}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfiguration) = preSolution
|
||||
Debug = Debug
|
||||
Release = Release
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectDependencies) = postSolution
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfiguration) = postSolution
|
||||
{572FFF74-480C-4472-8ABF-81733BB4049D}.Debug.ActiveCfg = Debug|Win32
|
||||
{572FFF74-480C-4472-8ABF-81733BB4049D}.Debug.Build.0 = Debug|Win32
|
||||
{572FFF74-480C-4472-8ABF-81733BB4049D}.Release.ActiveCfg = Release|Win32
|
||||
{572FFF74-480C-4472-8ABF-81733BB4049D}.Release.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityAddIns) = postSolution
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
@ -1,17 +1,40 @@
|
|||
Microsoft Visual Studio Solution File, Format Version 9.00
|
||||
# Visual C++ Express 2005
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vmap_assembler", "VC80\vmap_assembler.vcproj", "{572FFF74-480C-4472-8ABF-81733BB4049D}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2} = {8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}
|
||||
{8072769E-CF10-48BF-B9E1-12752A5DAC6E} = {8072769E-CF10-48BF-B9E1-12752A5DAC6E}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "..\..\win\VC80\zlib.vcproj", "{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "g3dlite", "..\..\win\VC80\g3dlite.vcproj", "{8072769E-CF10-48BF-B9E1-12752A5DAC6E}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug_NoPCH|Win32 = Debug_NoPCH|Win32
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{572FFF74-480C-4472-8ABF-81733BB4049D}.Debug_NoPCH|Win32.ActiveCfg = Debug|Win32
|
||||
{572FFF74-480C-4472-8ABF-81733BB4049D}.Debug_NoPCH|Win32.Build.0 = Debug|Win32
|
||||
{572FFF74-480C-4472-8ABF-81733BB4049D}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{572FFF74-480C-4472-8ABF-81733BB4049D}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{572FFF74-480C-4472-8ABF-81733BB4049D}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{572FFF74-480C-4472-8ABF-81733BB4049D}.Release|Win32.Build.0 = Release|Win32
|
||||
{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}.Debug_NoPCH|Win32.ActiveCfg = Debug_NoPCH|Win32
|
||||
{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}.Debug_NoPCH|Win32.Build.0 = Debug_NoPCH|Win32
|
||||
{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}.Release|Win32.Build.0 = Release|Win32
|
||||
{8072769E-CF10-48BF-B9E1-12752A5DAC6E}.Debug_NoPCH|Win32.ActiveCfg = Debug_NoPCH|Win32
|
||||
{8072769E-CF10-48BF-B9E1-12752A5DAC6E}.Debug_NoPCH|Win32.Build.0 = Debug_NoPCH|Win32
|
||||
{8072769E-CF10-48BF-B9E1-12752A5DAC6E}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{8072769E-CF10-48BF-B9E1-12752A5DAC6E}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{8072769E-CF10-48BF-B9E1-12752A5DAC6E}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{8072769E-CF10-48BF-B9E1-12752A5DAC6E}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
|
|||
|
|
@ -1,17 +1,40 @@
|
|||
Microsoft Visual Studio Solution File, Format Version 10.00
|
||||
# Visual Studio 2008
|
||||
# Visual C++ Express 2008
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vmap_assembler", "VC90\vmap_assembler.vcproj", "{572FFF74-480C-4472-8ABF-81733BB4049D}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2} = {8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}
|
||||
{8072769E-CF10-48BF-B9E1-12752A5DAC6E} = {8072769E-CF10-48BF-B9E1-12752A5DAC6E}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "..\..\win\VC90\zlib.vcproj", "{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "g3dlite", "..\..\win\VC90\g3dlite.vcproj", "{8072769E-CF10-48BF-B9E1-12752A5DAC6E}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug_NoPCH|Win32 = Debug_NoPCH|Win32
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{572FFF74-480C-4472-8ABF-81733BB4049D}.Debug_NoPCH|Win32.ActiveCfg = Debug|Win32
|
||||
{572FFF74-480C-4472-8ABF-81733BB4049D}.Debug_NoPCH|Win32.Build.0 = Debug|Win32
|
||||
{572FFF74-480C-4472-8ABF-81733BB4049D}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{572FFF74-480C-4472-8ABF-81733BB4049D}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{572FFF74-480C-4472-8ABF-81733BB4049D}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{572FFF74-480C-4472-8ABF-81733BB4049D}.Release|Win32.Build.0 = Release|Win32
|
||||
{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}.Debug_NoPCH|Win32.ActiveCfg = Debug_NoPCH|Win32
|
||||
{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}.Debug_NoPCH|Win32.Build.0 = Debug_NoPCH|Win32
|
||||
{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}.Release|Win32.Build.0 = Release|Win32
|
||||
{8072769E-CF10-48BF-B9E1-12752A5DAC6E}.Debug_NoPCH|Win32.ActiveCfg = Debug_NoPCH|Win32
|
||||
{8072769E-CF10-48BF-B9E1-12752A5DAC6E}.Debug_NoPCH|Win32.Build.0 = Debug_NoPCH|Win32
|
||||
{8072769E-CF10-48BF-B9E1-12752A5DAC6E}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{8072769E-CF10-48BF-B9E1-12752A5DAC6E}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{8072769E-CF10-48BF-B9E1-12752A5DAC6E}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{8072769E-CF10-48BF-B9E1-12752A5DAC6E}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,23 +0,0 @@
|
|||
Microsoft Visual Studio Solution File, Format Version 8.00
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vmapExtractor", "vmapExtractor_VC71.vcproj", "{87335BBF-5DA8-4FEC-A51E-1FB948F2FFE9}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfiguration) = preSolution
|
||||
Debug Ansi Static = Debug Ansi Static
|
||||
Release Ansi Static = Release Ansi Static
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectDependencies) = postSolution
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfiguration) = postSolution
|
||||
{87335BBF-5DA8-4FEC-A51E-1FB948F2FFE9}.Debug Ansi Static.ActiveCfg = Debug Ansi Static|Win32
|
||||
{87335BBF-5DA8-4FEC-A51E-1FB948F2FFE9}.Debug Ansi Static.Build.0 = Debug Ansi Static|Win32
|
||||
{87335BBF-5DA8-4FEC-A51E-1FB948F2FFE9}.Release Ansi Static.ActiveCfg = Release Ansi Static|Win32
|
||||
{87335BBF-5DA8-4FEC-A51E-1FB948F2FFE9}.Release Ansi Static.Build.0 = Release Ansi Static|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityAddIns) = postSolution
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
@ -1,786 +0,0 @@
|
|||
<?xml version="1.0" encoding="windows-1251"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.10"
|
||||
Name="vmapExtractor"
|
||||
ProjectGUID="{87335BBF-5DA8-4FEC-A51E-1FB948F2FFE9}"
|
||||
SccProjectName=""
|
||||
SccLocalPath="">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug Ansi Static|Win32"
|
||||
OutputDirectory=".\bin\Win32\DebugAS"
|
||||
IntermediateDirectory=".\bin\Win32\DebugAS"
|
||||
ConfigurationType="1"
|
||||
UseOfMFC="0"
|
||||
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=".\stormlib"
|
||||
PreprocessorDefinitions="_DEBUG;_CONSOLE;WIN32"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="5"
|
||||
UsePrecompiledHeader="2"
|
||||
PrecompiledHeaderFile=".\bin\Win32\DebugAS/StormLib.pch"
|
||||
AssemblerListingLocation=".\bin\Win32\DebugAS/"
|
||||
ObjectFile=".\bin\Win32\DebugAS/"
|
||||
ProgramDataBaseFileName=".\bin\Win32\DebugAS/"
|
||||
BrowseInformation="1"
|
||||
WarningLevel="4"
|
||||
SuppressStartupBanner="TRUE"
|
||||
DebugInformationFormat="4"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile=".\bin\Win32\DebugAS\vmapextract_v2.exe"
|
||||
LinkIncremental="2"
|
||||
SuppressStartupBanner="TRUE"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile=".\bin\Win32\DebugAS/StormLib.pdb"
|
||||
SubSystem="1"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TypeLibraryName=".\bin\StormLibTest\Win32\DebugAS/StormLibTest.tlb"
|
||||
HeaderFileName=""/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
PreprocessorDefinitions="_DEBUG"
|
||||
Culture="1029"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release Ansi Static|Win32"
|
||||
OutputDirectory=".\bin\Win32\ReleaseAS"
|
||||
IntermediateDirectory=".\bin\Win32\ReleaseAS"
|
||||
ConfigurationType="1"
|
||||
UseOfMFC="0"
|
||||
ATLMinimizesCRunTimeLibraryUsage="FALSE"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
InlineFunctionExpansion="1"
|
||||
AdditionalIncludeDirectories=".\stormlib"
|
||||
PreprocessorDefinitions="NDEBUG;_CONSOLE;WIN32"
|
||||
StringPooling="TRUE"
|
||||
RuntimeLibrary="4"
|
||||
EnableFunctionLevelLinking="TRUE"
|
||||
UsePrecompiledHeader="2"
|
||||
PrecompiledHeaderFile=".\bin\Win32\ReleaseAS/StormLib.pch"
|
||||
AssemblerListingLocation=".\bin\Win32\ReleaseAS/"
|
||||
ObjectFile=".\bin\Win32\ReleaseAS/"
|
||||
ProgramDataBaseFileName=".\bin\Win32\ReleaseAS/"
|
||||
WarningLevel="4"
|
||||
SuppressStartupBanner="TRUE"
|
||||
CompileAs="0"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile=".\bin\Win32\ReleaseAS\vmapextract_v2.exe"
|
||||
LinkIncremental="1"
|
||||
SuppressStartupBanner="TRUE"
|
||||
ProgramDatabaseFile=".\bin\Win32\ReleaseAS/StormLib.pdb"
|
||||
SubSystem="1"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
TypeLibraryName=".\bin\StormLibTest\Win32\ReleaseAS/StormLibTest.tlb"
|
||||
HeaderFileName=""/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
PreprocessorDefinitions="NDEBUG"
|
||||
Culture="1029"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
|
||||
<Filter
|
||||
Name="pklib"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="stormlib\pklib\crc32.c">
|
||||
<FileConfiguration
|
||||
Name="Debug Ansi Static|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
BasicRuntimeChecks="3"
|
||||
BrowseInformation="1"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release Ansi Static|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="stormlib\pklib\explode.c">
|
||||
<FileConfiguration
|
||||
Name="Debug Ansi Static|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
BasicRuntimeChecks="3"
|
||||
BrowseInformation="1"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release Ansi Static|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="stormlib\pklib\implode.c">
|
||||
<FileConfiguration
|
||||
Name="Debug Ansi Static|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
BasicRuntimeChecks="3"
|
||||
BrowseInformation="1"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release Ansi Static|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="stormlib\pklib\pklib.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="zlib"
|
||||
Filter="">
|
||||
<Filter
|
||||
Name="Zlib Headers"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="stormlib\zlib\zconf.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="stormlib\zlib\zlib.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Zlib Sources"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="stormlib\zlib\adler32.c">
|
||||
<FileConfiguration
|
||||
Name="Debug Ansi Static|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
BasicRuntimeChecks="3"
|
||||
BrowseInformation="1"
|
||||
WarningLevel="3"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release Ansi Static|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
WarningLevel="3"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="stormlib\zlib\deflate.c">
|
||||
<FileConfiguration
|
||||
Name="Debug Ansi Static|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
BasicRuntimeChecks="3"
|
||||
BrowseInformation="1"
|
||||
WarningLevel="3"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release Ansi Static|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
WarningLevel="3"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="stormlib\zlib\infblock.c">
|
||||
<FileConfiguration
|
||||
Name="Debug Ansi Static|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
BasicRuntimeChecks="3"
|
||||
BrowseInformation="1"
|
||||
WarningLevel="3"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release Ansi Static|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
WarningLevel="3"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="stormlib\zlib\infcodes.c">
|
||||
<FileConfiguration
|
||||
Name="Debug Ansi Static|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
BasicRuntimeChecks="3"
|
||||
BrowseInformation="1"
|
||||
WarningLevel="3"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release Ansi Static|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
WarningLevel="3"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="stormlib\zlib\inffast.c">
|
||||
<FileConfiguration
|
||||
Name="Debug Ansi Static|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
BasicRuntimeChecks="3"
|
||||
BrowseInformation="1"
|
||||
WarningLevel="3"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release Ansi Static|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
WarningLevel="3"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="stormlib\zlib\inflate.c">
|
||||
<FileConfiguration
|
||||
Name="Debug Ansi Static|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
BasicRuntimeChecks="3"
|
||||
BrowseInformation="1"
|
||||
WarningLevel="3"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release Ansi Static|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
WarningLevel="3"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="stormlib\zlib\inftrees.c">
|
||||
<FileConfiguration
|
||||
Name="Debug Ansi Static|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
BasicRuntimeChecks="3"
|
||||
BrowseInformation="1"
|
||||
WarningLevel="3"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release Ansi Static|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
WarningLevel="3"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="stormlib\zlib\infutil.c">
|
||||
<FileConfiguration
|
||||
Name="Debug Ansi Static|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
BasicRuntimeChecks="3"
|
||||
BrowseInformation="1"
|
||||
WarningLevel="3"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release Ansi Static|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
WarningLevel="3"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="stormlib\zlib\trees.c">
|
||||
<FileConfiguration
|
||||
Name="Debug Ansi Static|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
BasicRuntimeChecks="3"
|
||||
BrowseInformation="1"
|
||||
WarningLevel="3"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release Ansi Static|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
WarningLevel="3"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="stormlib\zlib\zmemory.c">
|
||||
<FileConfiguration
|
||||
Name="Debug Ansi Static|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
BasicRuntimeChecks="3"
|
||||
BrowseInformation="1"
|
||||
WarningLevel="3"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release Ansi Static|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
WarningLevel="3"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="huffman"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="stormlib\huffman\huff.cpp">
|
||||
<FileConfiguration
|
||||
Name="Debug Ansi Static|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
BasicRuntimeChecks="3"
|
||||
BrowseInformation="1"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release Ansi Static|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="stormlib\huffman\huff.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="wave"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="stormlib\wave\wave.cpp">
|
||||
<FileConfiguration
|
||||
Name="Debug Ansi Static|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
BasicRuntimeChecks="3"
|
||||
BrowseInformation="1"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release Ansi Static|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="stormlib\wave\wave.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="bzip2"
|
||||
Filter="*.h;*.c">
|
||||
<File
|
||||
RelativePath="stormlib\bzip2\blocksort.c">
|
||||
<FileConfiguration
|
||||
Name="Debug Ansi Static|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
BasicRuntimeChecks="3"
|
||||
BrowseInformation="1"
|
||||
WarningLevel="3"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release Ansi Static|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
WarningLevel="3"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="stormlib\bzip2\bzlib.c">
|
||||
<FileConfiguration
|
||||
Name="Debug Ansi Static|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
BasicRuntimeChecks="3"
|
||||
BrowseInformation="1"
|
||||
WarningLevel="3"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release Ansi Static|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
WarningLevel="3"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="stormlib\bzip2\compress.c">
|
||||
<FileConfiguration
|
||||
Name="Debug Ansi Static|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
BasicRuntimeChecks="3"
|
||||
BrowseInformation="1"
|
||||
WarningLevel="3"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release Ansi Static|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
WarningLevel="3"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="stormlib\bzip2\crctable.c">
|
||||
<FileConfiguration
|
||||
Name="Debug Ansi Static|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
BasicRuntimeChecks="3"
|
||||
BrowseInformation="1"
|
||||
WarningLevel="3"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release Ansi Static|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
WarningLevel="3"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="stormlib\bzip2\decompress.c">
|
||||
<FileConfiguration
|
||||
Name="Debug Ansi Static|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
BasicRuntimeChecks="3"
|
||||
BrowseInformation="1"
|
||||
WarningLevel="3"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release Ansi Static|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
WarningLevel="3"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="stormlib\bzip2\huffman.c">
|
||||
<FileConfiguration
|
||||
Name="Debug Ansi Static|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
BasicRuntimeChecks="3"
|
||||
BrowseInformation="1"
|
||||
WarningLevel="3"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release Ansi Static|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
WarningLevel="3"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="stormlib\bzip2\randtable.c">
|
||||
<FileConfiguration
|
||||
Name="Debug Ansi Static|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
BasicRuntimeChecks="3"
|
||||
BrowseInformation="1"
|
||||
WarningLevel="3"/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release Ansi Static|Win32">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
WarningLevel="3"/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="vmap"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath=".\vmapextract\adtfile.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\vmapextract\adtfile.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\vmapextract\dbcfile.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\vmapextract\dbcfile.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\vmapextract\model.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\vmapextract\model.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\vmapextract\modelheaders.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\vmapextract\mpq.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\vmapextract\mpq.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\vmapextract\vec3d.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\vmapextract\vmapexport.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\vmapextract\wdtfile.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\vmapextract\wdtfile.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\vmapextract\wmo.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\vmapextract\wmo.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="stormlib"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath=".\stormlib\SCommon.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\stormlib\SCommon.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\stormlib\SCompression.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\stormlib\SFileCompactArchive.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\stormlib\SFileCreateArchiveEx.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\stormlib\SFileExtractFile.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\stormlib\SFileFindFile.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\stormlib\SFileOpenArchive.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\stormlib\SFileOpenFileEx.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\stormlib\SFileReadFile.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\stormlib\SListFile.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\stormlib\StormDll.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\stormlib\StormLib.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\stormlib\StormPort.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\stormlib\StormPortLinux.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\stormlib\StormPortMac.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
|
|
@ -3,12 +3,12 @@
|
|||
|
||||
Axis-aligned box class
|
||||
|
||||
@maintainer Morgan McGuire, matrix@graphics3d.com
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2004-01-10
|
||||
@edited 2006-02-10
|
||||
@edited 2009-02-10
|
||||
|
||||
Copyright 2000-2006, Morgan McGuire.
|
||||
Copyright 2000-2009, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
|
@ -19,6 +19,7 @@
|
|||
#include "G3D/Vector3.h"
|
||||
#include "G3D/debug.h"
|
||||
#include "G3D/Array.h"
|
||||
#include "G3D/Plane.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
|
|
@ -27,6 +28,7 @@ namespace G3D {
|
|||
*/
|
||||
class AABox {
|
||||
private:
|
||||
friend class Intersect;
|
||||
|
||||
/** Optional argument placeholder */
|
||||
static int dummy;
|
||||
|
|
@ -42,7 +44,7 @@ public:
|
|||
/**
|
||||
Constructs a zero-area AABox at v.
|
||||
*/
|
||||
inline AABox(const Vector3& v) {
|
||||
inline explicit AABox(const Vector3& v) {
|
||||
lo = hi = v;
|
||||
}
|
||||
|
||||
|
|
@ -65,6 +67,26 @@ public:
|
|||
hi = high;
|
||||
}
|
||||
|
||||
/**
|
||||
Grows to include the bounds of a
|
||||
*/
|
||||
inline void merge(const AABox& a) {
|
||||
lo = lo.min(a.lo);
|
||||
hi = hi.max(a.hi);
|
||||
}
|
||||
|
||||
inline void merge(const Vector3& a) {
|
||||
lo = lo.min(a);
|
||||
hi = hi.max(a);
|
||||
}
|
||||
|
||||
void serialize(class BinaryOutput& b) const;
|
||||
|
||||
void deserialize(class BinaryInput& b);
|
||||
|
||||
inline bool isFinite() const {
|
||||
return lo.isFinite() && hi.isFinite();
|
||||
}
|
||||
|
||||
inline const Vector3& low() const {
|
||||
return lo;
|
||||
|
|
@ -77,20 +99,15 @@ public:
|
|||
/**
|
||||
The largest possible finite box.
|
||||
*/
|
||||
static inline const AABox& maxFinite() {
|
||||
static const AABox b = AABox(Vector3::minFinite(), Vector3::maxFinite());
|
||||
return b;
|
||||
}
|
||||
static const AABox& maxFinite();
|
||||
|
||||
static inline const AABox& inf() {
|
||||
static const AABox b = AABox(-Vector3::inf(), Vector3::inf());
|
||||
return b;
|
||||
}
|
||||
/** A large finite box. This is smaller than FLT_MAX
|
||||
because it leaves room to add boxes together. */
|
||||
static const AABox& large();
|
||||
|
||||
static inline const AABox& zero() {
|
||||
static const AABox b = AABox(Vector3::zero(), Vector3::zero());
|
||||
return b;
|
||||
}
|
||||
static const AABox& inf();
|
||||
|
||||
static const AABox& zero();
|
||||
|
||||
/**
|
||||
Returns the centroid of the box.
|
||||
|
|
@ -99,36 +116,21 @@ public:
|
|||
return (lo + hi) * 0.5;
|
||||
}
|
||||
|
||||
Vector3 corner(int index) const;
|
||||
|
||||
/**
|
||||
Distance from corner(0) to the next corner along axis a.
|
||||
*/
|
||||
inline double extent(int a) const {
|
||||
inline float extent(int a) const {
|
||||
debugAssert(a < 3);
|
||||
return hi[a] - lo[a];
|
||||
}
|
||||
|
||||
|
||||
inline Vector3 extent() const {
|
||||
return hi - lo;
|
||||
}
|
||||
|
||||
/**
|
||||
@deprecated Use culledBy(Array<Plane>&)
|
||||
*/
|
||||
bool culledBy(
|
||||
const class Plane* plane,
|
||||
int numPlanes,
|
||||
int32& cullingPlaneIndex,
|
||||
const uint32 testMask,
|
||||
uint32& childMask) const;
|
||||
|
||||
/**
|
||||
@deprecated Use culledBy(Array<Plane>&)
|
||||
*/
|
||||
bool culledBy(
|
||||
const class Plane* plane,
|
||||
int numPlanes,
|
||||
int32& cullingPlaneIndex = dummy,
|
||||
const uint32 testMask = 0xFFFFFF) const;
|
||||
|
||||
/**
|
||||
Splits the box into two AABoxes along the specified axis. low contains
|
||||
|
|
@ -176,7 +178,18 @@ public:
|
|||
bool culledBy(
|
||||
const Array<Plane>& plane,
|
||||
int32& cullingPlaneIndex = dummy,
|
||||
const uint32 testMask = -1) const;
|
||||
const uint32 testMask = 0xFFFFFFFF) const;
|
||||
|
||||
/** less than or equal to containment */
|
||||
inline bool contains(const AABox& other) const {
|
||||
return
|
||||
(other.hi.x <= hi.x) &&
|
||||
(other.hi.y <= hi.y) &&
|
||||
(other.hi.z <= hi.z) &&
|
||||
(other.lo.x >= lo.x) &&
|
||||
(other.lo.y >= lo.y) &&
|
||||
(other.lo.z >= lo.z);
|
||||
}
|
||||
|
||||
inline bool contains(
|
||||
const Vector3& point) const {
|
||||
|
|
@ -189,16 +202,11 @@ public:
|
|||
(point.z <= hi.z);
|
||||
}
|
||||
|
||||
/** @deprecated */
|
||||
inline float surfaceArea() const {
|
||||
inline float area() const {
|
||||
Vector3 diag = hi - lo;
|
||||
return 2.0f * (diag.x * diag.y + diag.y * diag.z + diag.x * diag.z);
|
||||
}
|
||||
|
||||
inline float area() const {
|
||||
return surfaceArea();
|
||||
}
|
||||
|
||||
inline float volume() const {
|
||||
Vector3 diag = hi - lo;
|
||||
return diag.x * diag.y * diag.z;
|
||||
|
|
@ -208,9 +216,6 @@ public:
|
|||
|
||||
Vector3 randomSurfacePoint() const;
|
||||
|
||||
/** @deprecated use Box constructor */
|
||||
class Box toBox() const;
|
||||
|
||||
/** Returns true if there is any overlap */
|
||||
bool intersects(const AABox& other) const;
|
||||
|
||||
|
|
@ -225,7 +230,7 @@ public:
|
|||
return AABox(L, H);
|
||||
}
|
||||
|
||||
inline unsigned int hashCode() const {
|
||||
inline size_t hashCode() const {
|
||||
return lo.hashCode() + hi.hashCode();
|
||||
}
|
||||
|
||||
|
|
@ -237,6 +242,20 @@ public:
|
|||
return !((lo == b.lo) && (hi == b.hi));
|
||||
}
|
||||
|
||||
inline AABox operator+(const Vector3& v) const {
|
||||
AABox out;
|
||||
out.lo = lo + v;
|
||||
out.hi = hi + v;
|
||||
return out;
|
||||
}
|
||||
|
||||
inline AABox operator-(const Vector3& v) const {
|
||||
AABox out;
|
||||
out.lo = lo - v;
|
||||
out.hi = hi - v;
|
||||
return out;
|
||||
}
|
||||
|
||||
void getBounds(AABox& out) const {
|
||||
out = *this;
|
||||
}
|
||||
|
|
@ -244,12 +263,10 @@ public:
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
Hashing function for use with Table.
|
||||
*/
|
||||
inline unsigned int hashCode(const G3D::AABox& b) {
|
||||
return b.hashCode();
|
||||
}
|
||||
template <> struct HashTrait<G3D::AABox> {
|
||||
static size_t hashCode(const G3D::AABox& key) { return key.hashCode(); }
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
|||
570
dep/include/g3dlite/G3D/Any.h
Normal file
570
dep/include/g3dlite/G3D/Any.h
Normal file
|
|
@ -0,0 +1,570 @@
|
|||
/**
|
||||
@file Any.h
|
||||
|
||||
@author Morgan McGuire, Shawn Yarbrough, and Corey Taylor
|
||||
@maintainer Morgan McGuire
|
||||
|
||||
@created 2006-06-11
|
||||
@edited 2009-12-16
|
||||
|
||||
Copyright 2000-2010, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_Any_h
|
||||
#define G3D_Any_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Table.h"
|
||||
#include "G3D/Array.h"
|
||||
#include "G3D/AtomicInt32.h"
|
||||
#include <string>
|
||||
|
||||
// needed for Token
|
||||
#include "G3D/TextInput.h"
|
||||
|
||||
#ifdef verify
|
||||
#undef verify
|
||||
#endif
|
||||
|
||||
namespace G3D {
|
||||
|
||||
class TextOutput;
|
||||
|
||||
/**
|
||||
\brief Easy loading and saving of human-readable configuration files.
|
||||
|
||||
Encodes typed, structured data and can serialize it to a human
|
||||
readable format that is very similar to the Python language's data
|
||||
syntax. Well-suited for quickly creating human-readable file formats,
|
||||
especially since deserialization and serialization preserve comments and
|
||||
an Any can tell you what file and line it came from.
|
||||
|
||||
The class is designed so that copying Anys generally is fast, even if
|
||||
it is a large array or table. This is because data is shared between
|
||||
copies until it is mutated, at which point an actual copy occurs.
|
||||
|
||||
\section Example
|
||||
Sample File:
|
||||
<pre>
|
||||
{
|
||||
shape = "round",
|
||||
|
||||
# in meters
|
||||
radius = 3.7,
|
||||
|
||||
position = Vector3(1.0, -1.0, 0.0),
|
||||
texture = { format = "RGB8", size = (320, 200)}
|
||||
}
|
||||
</pre>
|
||||
|
||||
Sample code using:
|
||||
<pre>
|
||||
Any x;
|
||||
x.load("ball.txt");
|
||||
if (x["shape"].string() == "round") {
|
||||
x["density"] = 3;
|
||||
}
|
||||
x.save("ball.txt");
|
||||
</pre>
|
||||
|
||||
The custom serialization format was chosen to be terse, easy for
|
||||
humans to read, and easy for machines to parse. It was specifically
|
||||
chosen over formats like XML, YAML, JSON, S-expressions, and Protocol
|
||||
Buffers, although there is no reason you could not write readers and
|
||||
writers for G3D::Any that support those.
|
||||
|
||||
G3D::Any assumes that structures do not contain cycles; it is an
|
||||
error to create a structure like:
|
||||
|
||||
<pre>
|
||||
Any x(Any::ARRAY);
|
||||
x.array().append(x); // don't do this!
|
||||
</pre>
|
||||
|
||||
although no exception will be thrown at runtime during that append.
|
||||
|
||||
|
||||
\section Parsing
|
||||
|
||||
The primary use of Any is to create your own text file formats.
|
||||
The Vector3 constructor is a good example of how to use the Any::verify
|
||||
methods to provide good error checking while parsing such formats:
|
||||
|
||||
<pre>
|
||||
Vector3::Vector3(const Any& any) {
|
||||
any.verifyName("Vector3");
|
||||
any.verifyType(Any::TABLE, Any::ARRAY);
|
||||
any.verifySize(3);
|
||||
|
||||
if (any.type() == Any::ARRAY) {
|
||||
x = any[0];
|
||||
y = any[1];
|
||||
z = any[2];
|
||||
} else {
|
||||
// Table
|
||||
x = any["x"];
|
||||
y = any["y"];
|
||||
z = any["z"];
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
\section BNF
|
||||
Serialized format BNF:
|
||||
|
||||
<pre>
|
||||
identifier ::= (letter | "_") (letter | digit | "_")*
|
||||
identifier-op ::= "::" | "->" | "."
|
||||
|
||||
identifier-exp ::= [identifier-op] identifier (identifier-op identifier)*
|
||||
|
||||
comment ::= "#" <any characters> "\n"
|
||||
separator ::= "," | ";"
|
||||
|
||||
number ::= <legal C printf number format>
|
||||
string ::= <legal C double-quoted string; backslashes must be escaped>
|
||||
boolean ::= "True" | "False"
|
||||
none ::= "None"
|
||||
array ::= "(" [value ("," value)*] ")"
|
||||
pair ::= (identifier | string) "=" value
|
||||
table ::= "{" [pair (separator pair)*] "}"
|
||||
named-array ::= identifier-exp tuple
|
||||
named-table ::= identifier-exp dict
|
||||
|
||||
value ::= [comment] (none | number | boolean | string | array | table | named-array | named-table)
|
||||
</pre>
|
||||
|
||||
Except for single-line comments, whitespace is not significant.
|
||||
All parsing is case-insensitive.
|
||||
|
||||
The deserializer allows the substitution of [] for () when writing
|
||||
tuples and ";" for ",".
|
||||
|
||||
The serializer indents four spaces for each level of nesting.
|
||||
Tables are written with the keys in alphabetic order.
|
||||
*/
|
||||
class Any {
|
||||
public:
|
||||
|
||||
enum Type {NONE, BOOLEAN, NUMBER, STRING, ARRAY, TABLE};
|
||||
|
||||
static std::string toString(Type t);
|
||||
|
||||
/** Where an Any came from in a file. Useful for throwing parsing errors */
|
||||
class Source {
|
||||
public:
|
||||
std::string filename;
|
||||
int line;
|
||||
int character;
|
||||
|
||||
Source() : line(0), character(0) {}
|
||||
|
||||
void set(const TextInput& ti, const Token& t) {
|
||||
filename = ti.filename();
|
||||
line = t.line();
|
||||
character = t.character();
|
||||
}
|
||||
};
|
||||
|
||||
typedef Array<Any> AnyArray;
|
||||
typedef Table<std::string, Any> AnyTable;
|
||||
|
||||
private:
|
||||
|
||||
/** Called from deserialize() */
|
||||
static void deserializeComment(TextInput& ti, Token& token, std::string& comment);
|
||||
|
||||
/** NONE, BOOLEAN, and NUMBER are stored directly in the Any */
|
||||
union SimpleValue {
|
||||
bool b;
|
||||
double n;
|
||||
|
||||
inline SimpleValue() : n(0.0) {}
|
||||
inline SimpleValue(bool x) : b(x) {}
|
||||
inline SimpleValue(double x) : n(x) {}
|
||||
};
|
||||
|
||||
class Data {
|
||||
public:
|
||||
/** ARRAY, TABLE, or STRING value only. NULL otherwise. */
|
||||
union Value {
|
||||
std::string* s;
|
||||
Array<Any>* a;
|
||||
AnyTable* t;
|
||||
inline Value() : s(NULL) {}
|
||||
};
|
||||
|
||||
// Needed so that the destructor knows what is in Value
|
||||
// and can call its destructor.
|
||||
Type type;
|
||||
|
||||
/** Always points to memory that is allocated with the Data, so
|
||||
the destructor does not delete this. */
|
||||
Value value;
|
||||
|
||||
std::string comment;
|
||||
|
||||
std::string name;
|
||||
|
||||
/** For STRING, ARRAY and TABLE types, m_value is shared between
|
||||
multiple instances. Mutation is allowed only if the reference
|
||||
count is exactly 1, otherwise the mutating instance must copy
|
||||
the value. This is not used for other types.
|
||||
*/
|
||||
AtomicInt32 referenceCount;
|
||||
|
||||
Source source;
|
||||
|
||||
private:
|
||||
|
||||
/** Called by create() */
|
||||
inline Data(Type t) : type(t), referenceCount(1) {}
|
||||
|
||||
/** Called by destroy */
|
||||
~Data();
|
||||
|
||||
public:
|
||||
|
||||
/** Clones the argument */
|
||||
static Data* create(const Data* d);
|
||||
static Data* create(Type t);
|
||||
|
||||
/** Free d, invoking its destructor and freeing the memory for
|
||||
the value. */
|
||||
static void destroy(Data* d);
|
||||
|
||||
};
|
||||
|
||||
/** If not empty, this Any was created from operator[] on a table
|
||||
and perhaps was not intended to exist. The name is needed to
|
||||
format the error message if it is read from before it is
|
||||
written to.
|
||||
|
||||
The source of a placeholder object is that of the parent
|
||||
object until it is written.
|
||||
*/
|
||||
std::string m_placeholderName;
|
||||
|
||||
Type m_type;
|
||||
SimpleValue m_simpleValue;
|
||||
mutable Data* m_data;
|
||||
|
||||
/** Called before every read operation to ensure that this object
|
||||
is not a placeholder. */
|
||||
void beforeRead() const;
|
||||
|
||||
/** Called before every write operation to wipe the placeholder
|
||||
status. */
|
||||
void beforeWrite();
|
||||
|
||||
/** Decrements the reference count (if there is one). If the
|
||||
reference count is zero after decrement, calls delete on @a m_data
|
||||
and sets it to NULL.
|
||||
*/
|
||||
void dropReference();
|
||||
|
||||
/** Allocate the Data object if it does not exist */
|
||||
void ensureData();
|
||||
|
||||
/** If m_data is not NULL, ensure that it has a unique reference
|
||||
and contains a valid m_data. This has a race condition if two
|
||||
threads are both trying to modify the same Any
|
||||
simultaneously.*/
|
||||
void ensureMutable();
|
||||
|
||||
/** Read an unnamed a TABLE or ARRAY. Token should be the open
|
||||
paren token; it is the next token after the close on
|
||||
return. Called from deserialize().*/
|
||||
void deserializeBody(TextInput& ti, Token& token);
|
||||
|
||||
void deserialize(TextInput& ti, Token& token);
|
||||
|
||||
/** Read the name of a named Array or Table. */
|
||||
static void deserializeName(TextInput& ti, Token& token, std::string& name);
|
||||
|
||||
/** Read until a comma is consumed or a close paren is hit, and
|
||||
return that token. Considers the passed in token to be the first
|
||||
value read. */
|
||||
static void readUntilCommaOrClose(TextInput& ti, Token& token);
|
||||
|
||||
/** Construct an Any that is a proxy for a table fetch from \a data.
|
||||
This proxy can be copied exactly once on return from operator[].*/
|
||||
Any(const std::string& key, Data* data);
|
||||
|
||||
inline bool isPlaceholder() const {
|
||||
return ! m_placeholderName.empty();
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/** Base class for all Any exceptions.*/
|
||||
class Exception {
|
||||
public:
|
||||
virtual ~Exception() {}
|
||||
};
|
||||
|
||||
/** Thrown by operator[] when a key is not present in a const table. */
|
||||
class KeyNotFound : public ParseError {
|
||||
public:
|
||||
std::string key;
|
||||
};
|
||||
|
||||
/** Thrown by operator[] when an array index is not present. */
|
||||
class IndexOutOfBounds : public Exception {
|
||||
public:
|
||||
int index;
|
||||
int size;
|
||||
inline IndexOutOfBounds() : index(0), size(0) {}
|
||||
inline IndexOutOfBounds(int i, int s) : index(i), size(s) {}
|
||||
};
|
||||
|
||||
/** NONE constructor */
|
||||
Any();
|
||||
|
||||
/** Deserialize */
|
||||
explicit Any(TextInput& t);
|
||||
|
||||
Any(const Any& x);
|
||||
|
||||
/** NUMBER constructor */
|
||||
Any(double x);
|
||||
|
||||
#ifdef G3D_32BIT
|
||||
/** NUMBER constructor */
|
||||
Any(int64 x);
|
||||
#endif // G3D_32BIT
|
||||
|
||||
#if 0
|
||||
/** NUMBER constructor */
|
||||
Any(int32 x);
|
||||
#endif // 0
|
||||
|
||||
/** NUMBER constructor */
|
||||
Any(long x);
|
||||
|
||||
/** NUMBER constructor */
|
||||
Any(int x);
|
||||
|
||||
/** NUMBER constructor */
|
||||
Any(short x);
|
||||
|
||||
/** BOOLEAN constructor */
|
||||
Any(bool x);
|
||||
|
||||
/** STRING constructor */
|
||||
Any(const std::string& x);
|
||||
|
||||
/** STRING constructor */
|
||||
Any(const char* x);
|
||||
|
||||
/** \a t must be ARRAY or TABLE */
|
||||
Any(Type t, const std::string& name = "");
|
||||
|
||||
~Any();
|
||||
|
||||
/** Removes the comment and name */
|
||||
Any& operator=(const Any& x);
|
||||
|
||||
/** Removes the comment and name */
|
||||
Any& operator=(double x);
|
||||
|
||||
/** Removes the comment and name */
|
||||
Any& operator=(int x);
|
||||
|
||||
/** Removes the comment and name */
|
||||
Any& operator=(bool x);
|
||||
|
||||
/** Removes the comment and name */
|
||||
Any& operator=(const std::string& x);
|
||||
|
||||
/** Removes the comment and name */
|
||||
Any& operator=(const char* x);
|
||||
|
||||
/** \a t must be ARRAY, TABLE, or NONE. Removes the comment and name */
|
||||
Any& operator=(Type t);
|
||||
|
||||
Type type() const;
|
||||
|
||||
/** Same as deserialize or load, but operates on a string instead
|
||||
of a stream or file.
|
||||
|
||||
\sa deserialize, load
|
||||
*/
|
||||
void parse(const std::string& src);
|
||||
|
||||
std::string unparse() const;
|
||||
|
||||
/** Comments appear before values when they are in serialized form.*/
|
||||
const std::string& comment() const;
|
||||
void setComment(const std::string& c);
|
||||
|
||||
/** True if this is the NONE value */
|
||||
bool isNone() const;
|
||||
|
||||
/** Throws a ParseError exception if this is not a number */
|
||||
double number() const;
|
||||
const std::string& string() const;
|
||||
bool boolean() const;
|
||||
|
||||
/** If this is named ARRAY or TABLE, returns the name. */
|
||||
const std::string& name() const;
|
||||
|
||||
/** \brief Set the name used when serializing an ARRAY or TABLE.
|
||||
|
||||
Only legal for ARRAY or TABLE. The \a name must begin with a letter
|
||||
and contain only letters, numbers, underscores and scope operators.
|
||||
|
||||
<pre>
|
||||
a2z
|
||||
hello
|
||||
Foo::bar
|
||||
color.red
|
||||
this->that
|
||||
__x
|
||||
</pre>
|
||||
|
||||
|
||||
The scope operators "::", "->", and
|
||||
".", may have spaces around them. The name may not
|
||||
contain parentheses.
|
||||
*/
|
||||
void setName(const std::string& name);
|
||||
|
||||
/** Number of elements if this is an ARRAY or TABLE */
|
||||
int size() const;
|
||||
int length() const;
|
||||
|
||||
/** For an array, returns the ith element */
|
||||
const Any& operator[](int i) const;
|
||||
Any& operator[](int i);
|
||||
|
||||
/** Directly exposes the underlying data structure for an ARRAY. */
|
||||
const Array<Any>& array() const;
|
||||
void append(const Any& v0);
|
||||
void append(const Any& v0, const Any& v1);
|
||||
void append(const Any& v0, const Any& v1, const Any& v2);
|
||||
void append(const Any& v0, const Any& v1, const Any& v2, const Any& v3);
|
||||
|
||||
/** Directly exposes the underlying data structure for table.*/
|
||||
const Table<std::string, Any>& table() const;
|
||||
|
||||
/** For a table, returns the element for \a key. Throws KeyNotFound
|
||||
exception if the element does not exist.
|
||||
*/
|
||||
const Any& operator[](const std::string& key) const;
|
||||
|
||||
// Needed to prevent the operator[](int) overload from catching
|
||||
// string literals
|
||||
inline const Any& operator[](const char* key) const {
|
||||
return operator[](std::string(key));
|
||||
}
|
||||
|
||||
/**
|
||||
Fetch an element from a table. This can be used as:
|
||||
|
||||
<pre>
|
||||
a["key"] = value; (create the key if it did not exist)
|
||||
</pre>
|
||||
|
||||
or
|
||||
|
||||
<pre>
|
||||
value = a["key"]; (throw an error if the key did not exist)
|
||||
</pre>
|
||||
|
||||
<b>Note:</b>
|
||||
In order to cause elements to be correctly created in the
|
||||
first case while still providing "key not found" errors in the
|
||||
second case, the Any returned is a special object that delays
|
||||
the actual fetch until the following assignment or method
|
||||
call. This means that in the event of an error, the exception
|
||||
may be thrown from a line other than the actual fetch. Use
|
||||
the Any::get() or the const Any::operator[]() methods to avoid
|
||||
this behavior and ensure error-checking at fetch time.
|
||||
*/
|
||||
Any& operator[](const std::string& key);
|
||||
|
||||
/** \copydoc Any::operator[](const std::string&) */
|
||||
inline Any& operator[](const char* key) {
|
||||
return operator[](std::string(key));
|
||||
}
|
||||
|
||||
/** For a table, returns the element for key \a x and \a
|
||||
defaultVal if it does not exist. */
|
||||
const Any& get(const std::string& key, const Any& defaultVal) const;
|
||||
|
||||
/** Returns true if this key is in the TABLE. Illegal to call on an object that is not a TABLE. */
|
||||
bool containsKey(const std::string& key) const;
|
||||
|
||||
/** For a table, assigns the element for key k. */
|
||||
void set(const std::string& key, const Any& val);
|
||||
|
||||
/** for an ARRAY, resizes and returns the last element */
|
||||
Any& next();
|
||||
|
||||
|
||||
/** True if the Anys are exactly equal, ignoring comments. Applies deeply on arrays and tables. */
|
||||
bool operator==(const Any& x) const;
|
||||
bool operator!=(const Any& x) const;
|
||||
|
||||
operator int() const;
|
||||
operator float() const;
|
||||
operator double() const;
|
||||
operator bool() const;
|
||||
operator std::string() const;
|
||||
|
||||
/** Resize to \a n elements, where new elements are NIL
|
||||
It is an error to call this method if this is not an Any::ARRAY */
|
||||
void resize(int n);
|
||||
|
||||
/**
|
||||
Clears all entries.
|
||||
This must be a TABLE or ARRAY */
|
||||
void clear();
|
||||
|
||||
/** Parse from a file.
|
||||
\sa deserialize, parse */
|
||||
void load(const std::string& filename);
|
||||
|
||||
/** Uses the serialize method. */
|
||||
void save(const std::string& filename) const;
|
||||
|
||||
void serialize(TextOutput& to) const;
|
||||
/** Parse from a stream.
|
||||
\sa load, parse */
|
||||
void deserialize(TextInput& ti);
|
||||
|
||||
const Source& source() const;
|
||||
|
||||
/** Throws a ParseError if \a value is false. Useful for quickly
|
||||
creating parse rules in classes that deserialize from Any.
|
||||
*/
|
||||
void verify(bool value, const std::string& message = "") const;
|
||||
|
||||
/** Verifies that the name begins with identifier \a n. It may contain
|
||||
identifier operators after this */
|
||||
void verifyName(const std::string& n) const;
|
||||
|
||||
/** Verifies that the type is \a t. */
|
||||
void verifyType(Type t) const;
|
||||
|
||||
/** Throws an exception if the type is not \a t0 or \a t1. */
|
||||
void verifyType(Type t0, Type t1) const;
|
||||
|
||||
/** Verifies that the size is between \a low and \a high, inclusive */
|
||||
void verifySize(int low, int high) const;
|
||||
|
||||
/** Verifies that the size is exactly \a s */
|
||||
void verifySize(int s) const;
|
||||
|
||||
private:
|
||||
|
||||
void deserializeTable(TextInput& ti);
|
||||
void deserializeArray(TextInput& ti,const std::string& term);
|
||||
|
||||
}; // class Any
|
||||
|
||||
} // namespace G3D
|
||||
|
||||
#endif
|
||||
512
dep/include/g3dlite/G3D/AnyVal.h
Normal file
512
dep/include/g3dlite/G3D/AnyVal.h
Normal file
|
|
@ -0,0 +1,512 @@
|
|||
/**
|
||||
@file AnyVal.h
|
||||
@author Morgan McGuire
|
||||
@created 2006-06-11
|
||||
@edited 2008-07-14
|
||||
*/
|
||||
|
||||
#ifndef G3D_ANYVAL_H
|
||||
#define G3D_ANYVAL_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include <string>
|
||||
#include "G3D/Array.h"
|
||||
#include "G3D/TextInput.h"
|
||||
|
||||
namespace G3D {
|
||||
// Forward declarations for G3D types
|
||||
class Vector2;
|
||||
class Vector3;
|
||||
class Vector4;
|
||||
class Color1;
|
||||
class Color3;
|
||||
class Color4;
|
||||
class Quat;
|
||||
class Matrix2;
|
||||
class Matrix3;
|
||||
class Matrix4;
|
||||
class CoordinateFrame;
|
||||
class TextInput;
|
||||
class TextOutput;
|
||||
class BinaryInput;
|
||||
class BinaryOutput;
|
||||
class Rect2D;
|
||||
class AABox;
|
||||
|
||||
/**
|
||||
\deprecated
|
||||
<b>Use the G3D::Any class instead. This is only provided for
|
||||
backwards compatibility to G3D 7.xx.</b>
|
||||
|
||||
A generic value, useful for defining property trees that can
|
||||
be loaded from and saved to disk. The values are intentionally
|
||||
restricted to a small set.
|
||||
|
||||
When written to files, the syntax is as follows. Note that you can
|
||||
nest arrays and tables in order to create full tree (i.e., XML-like)
|
||||
structures as configuration files:
|
||||
|
||||
<table>
|
||||
<tr><td>NULL</td><td><code>Nil</code></td></tr>
|
||||
<tr><td>double</td><td><i>The number in printf double format</i></td></tr>
|
||||
<tr><td>bool</td><td><code>true</code> <i>or</i> <code>false</code></td></tr>
|
||||
<tr><td>std::string</td><td><i>The string in double-quotes (</i><code>"</code><i>)</i></td></tr>
|
||||
<tr><td>Rect2D</td><td><code>R(</code><i>x<sub>0</sub></i><code>,</code><i>y<sub>0</sub></i><code>,</code><i>x<sub>1</sub></i><code>,</code><i>y<sub>1</sub></i><code>)</code></td></tr>
|
||||
<tr><td>Color1</td><td><code>C1(</code><i>value</i><code>)</code></td></tr>
|
||||
<tr><td>Color3</td><td><code>C3(</code><i>r</i><code>,</code><i>g</i><code>,</code><i>b</i><code>)</code></td></tr>
|
||||
<tr><td>Color4</td><td><code>C4(</code><i>r</i><code>,</code><i>g</i><code>,</code><i>b</i><code>,</code><i>a</i><code>)</code></td></tr>
|
||||
<tr><td>Vector2</td><td><code>V2(</code><i>x</i><code>,</code><i>y</i><code>)</code></td></tr>
|
||||
<tr><td>Vector3</td><td><code>V3(</code><i>x</i><code>,</code><i>y</i><code>,</code><i>z</i><code>)</code></td></tr>
|
||||
<tr><td>Vector4</td><td><code>V4(</code><i>x</i><code>,</code><i>y</i><code>,</code><i>z</i><code>,</code><i>w</i><code>)</code></td></tr>
|
||||
<tr><td>Quat</td><td><code>V(</code>x<code>,</code>y<code>,</code>z<code>,</code>w<code>)</code></td></tr>
|
||||
<tr><td>AABox</td><td><code>AAB(</code>low Vector3<code>, </code>high Vector3<code>)</code></td></tr>
|
||||
<tr><td>Matrix2</td><td><code>M2(</code>r0c0<code>, </code>r0c1<code>,
|
||||
<br> </code>r1c0<code>, </code>r1c1<code>)</code></td></tr>
|
||||
<tr><td>Matrix3</td><td><code>M3(</code>r0c0<code>, </code>r0c1<code>, </code>r0c2<code>,
|
||||
<br> </code>r1c0<code>, </code>r1c1<code>, </code>r1c2<code>,
|
||||
<br> </code>r2c0<code>, </code>r2c1<code>, </code>r2c2<code>)</code></td></tr>
|
||||
<tr><td>Matrix4</td><td><code>M4(</code>r0c0<code>, </code>r0c1<code>, </code>r0c2<code>, </code>r0c3<code>,
|
||||
<br> </code>r1c0<code>, </code>r1c1<code>, </code>r1c2<code>, </code>r1c3<code>,
|
||||
<br> </code>r2c0<code>, </code>r2c1<code>, </code>r2c2<code>, </code>r2c3<code>,
|
||||
<br> </code>r3c0<code>, </code>r3c1<code>, </code>r3c2<code>, </code>r3c3<code>)</code></td></tr>
|
||||
<tr><td>CoordinateFrame</td><td><code>CF(</code>r0c0<code>, </code>r0c1<code>, </code>r0c2<code>, </code>r0c3<code>,
|
||||
<br> </code>r1c0<code>, </code>r1c1<code>, </code>r1c2<code>, </code>r1c3<code>,
|
||||
<br> </code>r2c0<code>, </code>r2c1<code>, </code>r2c2<code>, </code>r2c3<code>)</code></td></tr>
|
||||
<tr><td>CoordinateFrame</td><td><code>CF(V3(</code><i>x</i><code>, </code><i>y</i><code>, </code><i>z</i><code>), </code><i>yaw deg</i><code>, </code><i>pitch deg</i><code>, </code><i>optional roll deg</i><code>)</code></td></tr>
|
||||
|
||||
<tr><td>Array</td><td><code>[</code><i>element<sub>0</sub></i><code>, </code><i>element<sub>1</sub></i><code>, </code> ... <code>, </code><i>element<sub>n-1</sub></i><code>]</code></td></tr>
|
||||
<tr><td>Table</td><td><code>{</code><i>symbol<sub>0</sub></i><code> = </code><i>value<sub>0</sub></i>
|
||||
<br><code> </code><i>symbol<sub>1</sub></i><code> = </code><i>value<sub>1</sub></i>
|
||||
<br><code> </code>...
|
||||
<br><code> </code><i>symbol<sub>n-1</sub></i><code> = </code><i>value<sub>n-1</sub></i><code>}</code></td></tr>
|
||||
</table>
|
||||
|
||||
See also boost::any for a more general purpose but slightly harder to use
|
||||
"any" for C++.
|
||||
|
||||
The semantics of operator[] and the get() methods are slightly different;
|
||||
operator[] acts more like a scripting language that automatically extends
|
||||
arrays and tables instead of generating errors. get() has more strict semantics,
|
||||
like a C++ class.
|
||||
|
||||
AnyVal uses copy-on-mutate, so that <code>AnyVal a = b</code> semantically copies <code>b</code> (like <code>int a = b</code> would), although in practice
|
||||
it delays the copy until one is mutated so that it is still fast to "copy" large arrays and tables.
|
||||
|
||||
Reading example:
|
||||
<pre>
|
||||
AnyVal property = AnyVal::fromFile("c:/tmp/test.txt"));
|
||||
|
||||
Vector3 vel = property["angular velocity"]
|
||||
|
||||
<i>Using defaults to handle errors:
|
||||
If there was no "enabled" value, this will return the default instead of failing</i>
|
||||
bool enabled = property["enabled"].boolean(true);
|
||||
|
||||
</pre>
|
||||
|
||||
Writing to a file:
|
||||
<pre>
|
||||
AnyVal dict(AnyVal::TABLE);
|
||||
|
||||
dict["enabled"] = AnyVal(true);
|
||||
dict["weight"] = 100;
|
||||
dict["angular velocity"] = Vector3(1, -3, 4.5);
|
||||
|
||||
TextOutput t("c:/tmp/test.txt");
|
||||
dict.serialize(t);
|
||||
t.commit();
|
||||
</pre>
|
||||
|
||||
Example of a data file:
|
||||
<pre>
|
||||
{
|
||||
heights = [1, 17, 32]
|
||||
model =
|
||||
{
|
||||
color = C3(1, 1, 1)
|
||||
filename = "foo.md2"
|
||||
}
|
||||
position = V3(23, 14, 0)
|
||||
name = "Elmer"
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
<b>What's the difference from boost::any?</b>
|
||||
<br>I think that AnyVal will be easier for novice C++ users. It addresses the problem that
|
||||
even though G3D::TextInput makes reading configuration files extremely simple, many people
|
||||
still don't use it. So AnyVal makes it ridiculously simple to read and write a tree of G3D
|
||||
types to a file.
|
||||
|
||||
<i>AnyVal:</i>
|
||||
<pre>
|
||||
{
|
||||
AnyVal tree(TextInput("config.txt"));
|
||||
|
||||
bool enabled = tree.get("enabled", false);
|
||||
Vector3 direction = tree.get("direction", Vector3::zero());
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
|
||||
<i>boost:</i>
|
||||
<pre>
|
||||
{
|
||||
bool enabled = false;
|
||||
Vector3 direction;
|
||||
Table<boost::any> tree;
|
||||
|
||||
...write lots of file parsing code...
|
||||
|
||||
if (tree.containsKey("enabled")) {
|
||||
const boost::any& val = tree["enabled"];
|
||||
try {
|
||||
enabled = any_cast<bool>(val);
|
||||
} catch(const boost::bad_any_cast &) {
|
||||
}
|
||||
}
|
||||
|
||||
if (tree.containsKey("direction")) {
|
||||
const boost::any& val = tree["direction"];
|
||||
try {
|
||||
direction = any_cast<Vector3>(val);
|
||||
} catch(const boost::bad_any_cast &) {
|
||||
}
|
||||
}
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
|
||||
\deprecated
|
||||
*/
|
||||
class AnyVal {
|
||||
public:
|
||||
|
||||
/** Array and table values are all Any.*/
|
||||
enum Type {
|
||||
NIL,
|
||||
NUMBER,
|
||||
BOOLEAN,
|
||||
STRING,
|
||||
VECTOR2,
|
||||
VECTOR3,
|
||||
VECTOR4,
|
||||
MATRIX2,
|
||||
MATRIX3,
|
||||
MATRIX4,
|
||||
QUAT,
|
||||
COORDINATEFRAME,
|
||||
COORDINATEFRAME2D,
|
||||
CFRAME = COORDINATEFRAME,
|
||||
CFRAME2D = COORDINATEFRAME2D,
|
||||
COLOR1,
|
||||
COLOR3,
|
||||
COLOR4,
|
||||
RECT2D,
|
||||
AABOX2D = RECT2D,
|
||||
AABOX,
|
||||
ARRAY,
|
||||
TABLE};
|
||||
|
||||
/** Base class for all AnyVal exceptions.*/
|
||||
class Exception {
|
||||
public:
|
||||
virtual ~Exception() {}
|
||||
};
|
||||
|
||||
/** Thrown when an inappropriate operation is performed (e.g., operator[] on a number) */
|
||||
class WrongType : public Exception {
|
||||
public:
|
||||
Type expected;
|
||||
Type actual;
|
||||
WrongType() : expected(NIL), actual(NIL) {}
|
||||
WrongType(Type e, Type a) : expected(e), actual(a) {}
|
||||
};
|
||||
|
||||
/** Thrown by operator[] when a key is not present. */
|
||||
class KeyNotFound : public Exception {
|
||||
public:
|
||||
std::string key;
|
||||
KeyNotFound() {}
|
||||
KeyNotFound(const std::string& k) : key(k) {}
|
||||
};
|
||||
|
||||
class IndexOutOfBounds : public Exception {
|
||||
public:
|
||||
int index;
|
||||
int size;
|
||||
IndexOutOfBounds() : index(0), size(0) {}
|
||||
IndexOutOfBounds(int i, int s) : index(i), size(s) {}
|
||||
};
|
||||
|
||||
/** Thrown when deserialize() when the input is incorrectly formatted. */
|
||||
class CorruptText : public Exception {
|
||||
public:
|
||||
std::string message;
|
||||
|
||||
/** Token where the problem occurred.*/
|
||||
G3D::Token token;
|
||||
|
||||
CorruptText() {}
|
||||
CorruptText(const std::string& s, const G3D::Token& t) : message(s), token(t) {}
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
Type m_type;
|
||||
void* m_value;
|
||||
|
||||
/** For table and array types, *m_value is shared between multiple
|
||||
instances. Mutation is allowed only if the reference count is
|
||||
exactly 1, otherwise the mutating instance must copy the
|
||||
value. This is not used for other types.
|
||||
*/
|
||||
int* m_referenceCount;
|
||||
|
||||
/** Decrements the reference count (if there is one). If the
|
||||
reference count is zero or does not exist. Calls delete on @a
|
||||
m_value and sets it to NULL.
|
||||
*/
|
||||
void deleteValue();
|
||||
|
||||
/** Returns a copy of the value. */
|
||||
void* copyValue() const;
|
||||
|
||||
/** Assumes isSharedType. Ensures that this has a unique reference */
|
||||
void makeMutable();
|
||||
|
||||
/** True if this is a shared value between multiple instances. */
|
||||
inline bool isShared() const {
|
||||
return m_referenceCount && (*m_referenceCount > 1);
|
||||
}
|
||||
|
||||
/** True when m_value is a double pointer */
|
||||
inline bool isSharedType() const {
|
||||
return (m_type == TABLE) || (m_type == ARRAY);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
AnyVal();
|
||||
|
||||
/** Deserialize */
|
||||
explicit AnyVal(G3D::TextInput& t);
|
||||
|
||||
static AnyVal fromFile(const std::string& filename);
|
||||
|
||||
void load(const std::string& filename);
|
||||
|
||||
void save(const std::string& filename) const;
|
||||
|
||||
///** Deserialize */
|
||||
//explicit AnyVal(G3D::BinaryInput& t);
|
||||
|
||||
/** Construct a number */
|
||||
AnyVal(double);
|
||||
AnyVal(int);
|
||||
|
||||
// Explicit to avoid ambiguity with the 'double' constructor
|
||||
// when an integer type is constructed
|
||||
AnyVal(bool);
|
||||
AnyVal(const G3D::Vector2&);
|
||||
AnyVal(const G3D::Vector3&);
|
||||
AnyVal(const G3D::Vector4&);
|
||||
|
||||
AnyVal(const G3D::Color1&);
|
||||
AnyVal(const G3D::Color3&);
|
||||
AnyVal(const G3D::Color4&);
|
||||
|
||||
AnyVal(const std::string&);
|
||||
AnyVal(const char*);
|
||||
|
||||
AnyVal(const G3D::Quat&);
|
||||
|
||||
AnyVal(const G3D::Rect2D&);
|
||||
AnyVal(const G3D::AABox&);
|
||||
|
||||
AnyVal(const G3D::CoordinateFrame&);
|
||||
AnyVal(const G3D::Matrix2&);
|
||||
AnyVal(const G3D::Matrix3&);
|
||||
AnyVal(const G3D::Matrix4&);
|
||||
|
||||
AnyVal(const AnyVal&);
|
||||
|
||||
AnyVal(Type arrayOrTable);
|
||||
|
||||
AnyVal& operator=(const AnyVal&);
|
||||
|
||||
/** Frees the underlying storage */
|
||||
~AnyVal();
|
||||
|
||||
Type type() const;
|
||||
|
||||
bool isNil() const {
|
||||
return type() == NIL;
|
||||
}
|
||||
|
||||
void serialize(G3D::TextOutput& t) const;
|
||||
//void serialize(G3D::BinaryOutput& t) const;
|
||||
void deserialize(G3D::TextInput& t);
|
||||
//void deserialize(G3D::BinaryInput& t);
|
||||
|
||||
/** Array dereference. If the index is out of bounds, IndexOutOfBounds is thrown */
|
||||
const AnyVal& operator[](int) const;
|
||||
|
||||
/** Extend this array by one element. */
|
||||
void append(const AnyVal&);
|
||||
|
||||
/** If the index is out of bounds, the array is resized. If the index is negative,
|
||||
IndexOutOfBounds is thrown.*/
|
||||
AnyVal& operator[](int);
|
||||
|
||||
/** If @a i is out of bounds or this is not an ARRAY, defaultVal is returned.*/
|
||||
const AnyVal& get(int i, const AnyVal& defaultVal) const;
|
||||
|
||||
/** If out of bounds, IndexOutOfBounds is thrown. */
|
||||
const AnyVal& get(int i) const;
|
||||
|
||||
/** Returns defaultVal if this is not a TABLE or the key is not found. */
|
||||
const AnyVal& get(const std::string& key, const AnyVal& defaultVal) const;
|
||||
|
||||
/** Throws KeyNotFound exception if the key is not present.*/
|
||||
const AnyVal& get(const std::string& key) const;
|
||||
|
||||
/** Table reference */
|
||||
const AnyVal& operator[](const std::string&) const;
|
||||
|
||||
/** Table reference. If the element does not exist, it is created. */
|
||||
AnyVal& operator[](const std::string&);
|
||||
|
||||
/** Table reference */
|
||||
const AnyVal& operator[](const char*) const;
|
||||
|
||||
/** Table reference. If the element does not exist, it is created. */
|
||||
AnyVal& operator[](const char*);
|
||||
|
||||
/** If this value is not a number throws a WrongType exception. */
|
||||
double number() const;
|
||||
|
||||
/** If this value is not a number, returns defaultVal. */
|
||||
double number(double defaultVal) const;
|
||||
|
||||
operator double () const {
|
||||
return number();
|
||||
}
|
||||
|
||||
operator float () const {
|
||||
return (float)number();
|
||||
}
|
||||
|
||||
bool boolean() const;
|
||||
bool boolean(bool b) const;
|
||||
|
||||
operator bool() const {
|
||||
return boolean();
|
||||
}
|
||||
|
||||
const std::string& string() const;
|
||||
const std::string& string(const std::string& defaultVal) const;
|
||||
|
||||
operator const std::string& () const {
|
||||
return string();
|
||||
}
|
||||
|
||||
const G3D::Rect2D& rect2D() const;
|
||||
const G3D::Rect2D& rect2D(const G3D::Rect2D& defaultVal) const;
|
||||
|
||||
operator const Rect2D& () const {
|
||||
return rect2D();
|
||||
}
|
||||
|
||||
const G3D::AABox& aabox() const;
|
||||
const G3D::AABox& aabox(const G3D::AABox& defaultVal) const;
|
||||
|
||||
operator const AABox& () const {
|
||||
return aabox();
|
||||
}
|
||||
|
||||
const G3D::Vector2& vector2() const;
|
||||
const G3D::Vector2& vector2(const G3D::Vector2& defaultVal) const;
|
||||
|
||||
operator const Vector2& () const {
|
||||
return vector2();
|
||||
}
|
||||
|
||||
const G3D::Vector3& vector3() const;
|
||||
const G3D::Vector3& vector3(const G3D::Vector3& defaultVal) const;
|
||||
|
||||
operator const Vector3& () {
|
||||
return vector3();
|
||||
}
|
||||
|
||||
const G3D::Vector4& vector4() const;
|
||||
const G3D::Vector4& vector4(const G3D::Vector4& defaultVal) const;
|
||||
|
||||
operator const Vector4& () const {
|
||||
return vector4();
|
||||
}
|
||||
|
||||
const G3D::Color1& color1() const;
|
||||
const G3D::Color1& color1(const G3D::Color1& defaultVal) const;
|
||||
|
||||
const G3D::Color3& color3() const;
|
||||
const G3D::Color3& color3(const G3D::Color3& defaultVal) const;
|
||||
|
||||
operator const Color3& () const {
|
||||
return color3();
|
||||
}
|
||||
|
||||
const G3D::Color4& color4() const;
|
||||
const G3D::Color4& color4(const G3D::Color4& defaultVal) const;
|
||||
|
||||
operator const Color4& () const {
|
||||
return color4();
|
||||
}
|
||||
|
||||
const G3D::CoordinateFrame& coordinateFrame() const;
|
||||
const G3D::CoordinateFrame& coordinateFrame(const G3D::CoordinateFrame& defaultVal) const;
|
||||
|
||||
operator const CoordinateFrame& () const {
|
||||
return coordinateFrame();
|
||||
}
|
||||
|
||||
const G3D::Matrix2& matrix2() const;
|
||||
const G3D::Matrix2& matrix2(const G3D::Matrix2& defaultVal) const;
|
||||
|
||||
operator const Matrix2& () const {
|
||||
return matrix2();
|
||||
}
|
||||
|
||||
const G3D::Matrix3& matrix3() const;
|
||||
const G3D::Matrix3& matrix3(const G3D::Matrix3& defaultVal) const;
|
||||
|
||||
operator const Matrix3& () const {
|
||||
return matrix3();
|
||||
}
|
||||
|
||||
const G3D::Matrix4& matrix4() const;
|
||||
const G3D::Matrix4& matrix4(const G3D::Matrix4& defaultVal) const;
|
||||
|
||||
operator const Matrix4& () const {
|
||||
return matrix4();
|
||||
}
|
||||
|
||||
const G3D::Quat& quat() const;
|
||||
const G3D::Quat& quat(const G3D::Quat& defaultVal) const;
|
||||
|
||||
operator const Quat& () const {
|
||||
return quat();
|
||||
}
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
/** Number of elements for an array or table.*/
|
||||
int size() const;
|
||||
|
||||
/** For a table, returns the keys. */
|
||||
void getKeys(G3D::Array<std::string>&) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
93
dep/include/g3dlite/G3D/AreaMemoryManager.h
Normal file
93
dep/include/g3dlite/G3D/AreaMemoryManager.h
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
/**
|
||||
@file AreaMemoryManager.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2009-01-20
|
||||
@edited 2009-05-29
|
||||
|
||||
Copyright 2000-2009, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef G3D_AreaMemoryManager_h
|
||||
#define G3D_AreaMemoryManager_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/Array.h"
|
||||
#include "G3D/MemoryManager.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
\brief Allocates memory in large blocks and then frees it as an area.
|
||||
|
||||
Useful for ensuring cache coherence and for reducing the time cost of
|
||||
multiple allocations and deallocations.
|
||||
|
||||
<b>Not threadsafe</b>
|
||||
*/
|
||||
class AreaMemoryManager : public MemoryManager {
|
||||
private:
|
||||
|
||||
class Buffer {
|
||||
private:
|
||||
uint8* m_first;
|
||||
size_t m_size;
|
||||
size_t m_used;
|
||||
|
||||
public:
|
||||
|
||||
Buffer(size_t size);
|
||||
|
||||
~Buffer();
|
||||
|
||||
/** Returns NULL if out of space */
|
||||
void* alloc(size_t s);
|
||||
};
|
||||
|
||||
size_t m_sizeHint;
|
||||
|
||||
/** The underlying array is stored in regular MemoryManager heap memory */
|
||||
Array<Buffer*> m_bufferArray;
|
||||
|
||||
AreaMemoryManager(size_t sizeHint);
|
||||
|
||||
public:
|
||||
|
||||
typedef ReferenceCountedPointer<AreaMemoryManager> Ref;
|
||||
|
||||
/**
|
||||
\param sizeHint Total amount of memory expected to be allocated.
|
||||
The allocator will allocate memory from the system in increments
|
||||
of this size.
|
||||
*/
|
||||
static AreaMemoryManager::Ref create(size_t sizeHint = 10 * 1024 * 1024);
|
||||
|
||||
/** Invokes deallocateAll. */
|
||||
~AreaMemoryManager();
|
||||
|
||||
size_t bytesAllocated() const;
|
||||
|
||||
/** Allocates memory out of the buffer pool.
|
||||
@param s must be no larger than sizeHint */
|
||||
virtual void* alloc(size_t s);
|
||||
|
||||
/** Ignored. */
|
||||
virtual void free(void* x);
|
||||
|
||||
virtual bool isThreadsafe() const;
|
||||
|
||||
/** Deletes all previously allocated memory. Because delete is not
|
||||
invoked on objects in this memory, it is not safe to simply
|
||||
free memory containing C++ objects that expect their destructors
|
||||
to be called. */
|
||||
void deallocateAll();
|
||||
};
|
||||
|
||||
typedef AreaMemoryManager CoherentAllocator;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -5,18 +5,19 @@
|
|||
@cite Portions written by Aaron Orenstein, a@orenstein.name
|
||||
|
||||
@created 2001-03-11
|
||||
@edited 2007-05-12
|
||||
@edited 2009-05-29
|
||||
|
||||
Copyright 2000-2007, Morgan McGuire.
|
||||
Copyright 2000-2009, Morgan McGuire, http://graphics.cs.williams.edu
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_ARRAY_H
|
||||
#define G3D_ARRAY_H
|
||||
#ifndef G3D_Array_h
|
||||
#define G3D_Array_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/debug.h"
|
||||
#include "G3D/System.h"
|
||||
#include "G3D/MemoryManager.h"
|
||||
#ifdef G3D_DEBUG
|
||||
// For formatting error messages
|
||||
# include "G3D/format.h"
|
||||
|
|
@ -24,7 +25,7 @@
|
|||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#ifdef G3D_WIN32
|
||||
#ifdef _MSC_VER
|
||||
# include <new>
|
||||
|
||||
# pragma warning (push)
|
||||
|
|
@ -47,7 +48,7 @@ const int SORT_INCREASING = 1;
|
|||
const int SORT_DECREASING = -1;
|
||||
|
||||
/**
|
||||
Dynamic 1D array.
|
||||
\brief Dynamic 1D array tuned for performance.
|
||||
|
||||
Objects must have a default constructor (constructor that
|
||||
takes no arguments) in order to be used with this template.
|
||||
|
|
@ -57,20 +58,15 @@ const int SORT_DECREASING = -1;
|
|||
Do not use with objects that overload placement <code>operator new</code>,
|
||||
since the speed of Array is partly due to pooled allocation.
|
||||
|
||||
If SSE is defined Arrays allocate the first element aligned to
|
||||
16 bytes.
|
||||
|
||||
|
||||
Array is highly optimized compared to std::vector.
|
||||
Array operations are less expensive than on std::vector and for large
|
||||
amounts of data, Array consumes only 1.5x the total size of the
|
||||
data, while std::vector consumes 2.0x. The default
|
||||
array takes up zero heap space. The first resize (or append)
|
||||
operation grows it to a reasonable internal size so it is efficient
|
||||
to append to small arrays. Memory is allocated using
|
||||
System::alignedMalloc, which produces pointers aligned to 16-byte
|
||||
boundaries for use with SSE instructions and uses pooled storage for
|
||||
fast allocation. When Array needs to copy
|
||||
to append to small arrays.
|
||||
|
||||
Then Array needs to copy
|
||||
data internally on a resize operation it correctly invokes copy
|
||||
constructors of the elements (the MSVC6 implementation of
|
||||
std::vector uses realloc, which can create memory leaks for classes
|
||||
|
|
@ -81,24 +77,38 @@ const int SORT_DECREASING = -1;
|
|||
|
||||
To serialize an array, see G3D::serialize.
|
||||
|
||||
The template parameter MIN_ELEMENTS indicates the smallest number of
|
||||
elements that will be allocated. The default of 10 is designed to avoid
|
||||
the overhead of repeatedly allocating the array as it grows from 1, to 2, and so on.
|
||||
If you are creating a lot of small Arrays, however, you may want to set this smaller
|
||||
to reduce the memory cost. Once the array has been allocated, it will never
|
||||
deallocate the underlying array unless MIN_ELEMENTS is set to 0, MIN_BYTES is 0, and the array
|
||||
is empty.
|
||||
|
||||
Do not subclass an Array.
|
||||
|
||||
\sa G3D::SmallArray
|
||||
*/
|
||||
template <class T>
|
||||
template <class T, int MIN_ELEMENTS = 10, size_t MIN_BYTES = 32>
|
||||
class Array {
|
||||
private:
|
||||
/** 0...num-1 are initialized elements, num...numAllocated-1 are not */
|
||||
T* data;
|
||||
T* data;
|
||||
|
||||
int num;
|
||||
int numAllocated;
|
||||
int num;
|
||||
int numAllocated;
|
||||
|
||||
void init(int n, int a) {
|
||||
debugAssert(n <= a);
|
||||
MemoryManager::Ref m_memoryManager;
|
||||
|
||||
/** \param n Number of elements
|
||||
*/
|
||||
void init(int n, const MemoryManager::Ref& m) {
|
||||
m_memoryManager = m;
|
||||
debugAssert(n >= 0);
|
||||
this->num = 0;
|
||||
this->numAllocated = 0;
|
||||
data = NULL;
|
||||
if (a > 0) {
|
||||
if (n > 0) {
|
||||
resize(n);
|
||||
} else {
|
||||
data = NULL;
|
||||
|
|
@ -106,7 +116,7 @@ private:
|
|||
}
|
||||
|
||||
void _copy(const Array &other) {
|
||||
init(other.num, other.num);
|
||||
init(other.num, MemoryManager::create());
|
||||
for (int i = 0; i < num; i++) {
|
||||
data[i] = other.data[i];
|
||||
}
|
||||
|
|
@ -140,10 +150,11 @@ private:
|
|||
// elements are actually revealed to the application. They
|
||||
// will be constructed in the resize() method.
|
||||
|
||||
data = (T*)System::alignedMalloc(sizeof(T) * numAllocated, 16);
|
||||
data = (T*)m_memoryManager->alloc(sizeof(T) * numAllocated);
|
||||
alwaysAssertM(data, "Memory manager returned NULL: out of memory?");
|
||||
|
||||
// Call the copy constructors
|
||||
{const int N = iMin(oldNum, numAllocated);
|
||||
{const int N = G3D::min(oldNum, numAllocated);
|
||||
const T* end = data + N;
|
||||
T* oldPtr = oldData;
|
||||
for (T* ptr = data; ptr < end; ++ptr, ++oldPtr) {
|
||||
|
|
@ -163,20 +174,31 @@ private:
|
|||
ptr->~T();
|
||||
}}
|
||||
|
||||
|
||||
System::alignedFree(oldData);
|
||||
m_memoryManager->free(oldData);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
C++ STL style iterator variable. Call begin() to get
|
||||
G3D C++ STL style iterator variable. Call begin() to get
|
||||
the first iterator, pre-increment (++i) the iterator to get to
|
||||
the next value. Use dereference (*i) to access the element.
|
||||
*/
|
||||
typedef T* Iterator;
|
||||
/** G3D C++ STL style const iterator in same style as Iterator. */
|
||||
typedef const T* ConstIterator;
|
||||
|
||||
/** stl porting compatibility helper */
|
||||
typedef Iterator iterator;
|
||||
/** stl porting compatibility helper */
|
||||
typedef ConstIterator const_iterator;
|
||||
/** stl porting compatibility helper */
|
||||
typedef T value_type;
|
||||
/** stl porting compatibility helper */
|
||||
typedef int size_type;
|
||||
/** stl porting compatibility helper */
|
||||
typedef int difference_type;
|
||||
|
||||
/**
|
||||
C++ STL style iterator method. Returns the first iterator element.
|
||||
Do not change the size of the array while iterating.
|
||||
|
|
@ -216,23 +238,60 @@ public:
|
|||
return data;
|
||||
}
|
||||
|
||||
/** Creates a zero length array (no heap allocation occurs until resize). */
|
||||
Array() {
|
||||
init(0, 0);
|
||||
}
|
||||
/** Creates a zero length array (no heap allocation occurs until resize). */
|
||||
Array() : num(0) {
|
||||
init(0, MemoryManager::create());
|
||||
debugAssert(num >= 0);
|
||||
}
|
||||
|
||||
|
||||
/** Creates an array containing v0. */
|
||||
Array(const T& v0) {
|
||||
init(1, MemoryManager::create());
|
||||
(*this)[0] = v0;
|
||||
}
|
||||
|
||||
/** Creates an array containing v0 and v1. */
|
||||
Array(const T& v0, const T& v1) {
|
||||
init(2, MemoryManager::create());
|
||||
(*this)[0] = v0;
|
||||
(*this)[1] = v1;
|
||||
}
|
||||
|
||||
/** Creates an array containing v0...v2. */
|
||||
Array(const T& v0, const T& v1, const T& v2) {
|
||||
init(3, MemoryManager::create());
|
||||
(*this)[0] = v0;
|
||||
(*this)[1] = v1;
|
||||
(*this)[2] = v2;
|
||||
}
|
||||
|
||||
/** Creates an array containing v0...v3. */
|
||||
Array(const T& v0, const T& v1, const T& v2, const T& v3) {
|
||||
init(4, MemoryManager::create());
|
||||
(*this)[0] = v0;
|
||||
(*this)[1] = v1;
|
||||
(*this)[2] = v2;
|
||||
(*this)[3] = v3;
|
||||
}
|
||||
|
||||
/** Creates an array containing v0...v4. */
|
||||
Array(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4) {
|
||||
init(5, MemoryManager::create());
|
||||
(*this)[0] = v0;
|
||||
(*this)[1] = v1;
|
||||
(*this)[2] = v2;
|
||||
(*this)[3] = v3;
|
||||
(*this)[4] = v4;
|
||||
}
|
||||
|
||||
/**
|
||||
Creates an array of size.
|
||||
*/
|
||||
Array(int size) {
|
||||
init(size, size);
|
||||
}
|
||||
|
||||
/**
|
||||
Copy constructor
|
||||
*/
|
||||
Array(const Array& other) {
|
||||
Array(const Array& other) : num(0) {
|
||||
_copy(other);
|
||||
debugAssert(num >= 0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -248,36 +307,43 @@ public:
|
|||
(data + i)->~T();
|
||||
}
|
||||
|
||||
System::alignedFree(data);
|
||||
m_memoryManager->free(data);
|
||||
// Set to 0 in case this Array is global and gets referenced during app exit
|
||||
data = NULL;
|
||||
num = 0;
|
||||
numAllocated = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Removes all elements. Use resize(0, false) or fastClear if you want to
|
||||
remove all elements without deallocating the underlying array
|
||||
so that future append() calls will be faster.
|
||||
*/
|
||||
void clear() {
|
||||
resize(0);
|
||||
void clear(bool shrink = true) {
|
||||
resize(0, shrink);
|
||||
}
|
||||
|
||||
/** resize(0, false) */
|
||||
void clearAndSetMemoryManager(const MemoryManager::Ref& m) {
|
||||
clear();
|
||||
debugAssert(data == NULL);
|
||||
m_memoryManager = m;
|
||||
}
|
||||
|
||||
/** resize(0, false)
|
||||
@deprecated*/
|
||||
void fastClear() {
|
||||
resize(0, false);
|
||||
clear(false);
|
||||
}
|
||||
|
||||
/**
|
||||
Assignment operator.
|
||||
*/
|
||||
Array& operator=(const Array& other) {
|
||||
resize(other.num);
|
||||
for (int i = 0; i < num; ++i) {
|
||||
debugAssert(num >= 0);
|
||||
resize(other.num); for (int i = 0; i < num; ++i) {
|
||||
data[i] = other[i];
|
||||
}
|
||||
debugAssert(num >= 0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -289,6 +355,10 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
inline MemoryManager::Ref memoryManager() const {
|
||||
return m_memoryManager;
|
||||
}
|
||||
|
||||
/**
|
||||
Number of elements in the array.
|
||||
*/
|
||||
|
|
@ -308,25 +378,11 @@ public:
|
|||
Swaps element index with the last element in the array then
|
||||
shrinks the array by one.
|
||||
*/
|
||||
void fastRemove(int index) {
|
||||
void fastRemove(int index, bool shrinkIfNecessary = false) {
|
||||
debugAssert(index >= 0);
|
||||
debugAssert(index < num);
|
||||
data[index] = data[num - 1];
|
||||
resize(size() - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
Resizes, calling the default constructor for
|
||||
newly created objects and shrinking the underlying
|
||||
array as needed (and calling destructors as needed).
|
||||
*/
|
||||
void resize(int n) {
|
||||
resize(n, true);
|
||||
}
|
||||
|
||||
/** Resizes without shrinking the underlying array */
|
||||
void fastResize(int n) {
|
||||
resize(n, false);
|
||||
resize(size() - 1, shrinkIfNecessary);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -345,20 +401,34 @@ public:
|
|||
|
||||
/** @param shrinkIfNecessary if false, memory will never be
|
||||
reallocated when the array shrinks. This makes resizing much
|
||||
faster but can waste memory. */
|
||||
void resize(int n, bool shrinkIfNecessary) {
|
||||
int oldNum = num;
|
||||
num = n;
|
||||
faster but can waste memory.
|
||||
*/
|
||||
void resize(int n, bool shrinkIfNecessary = true) {
|
||||
debugAssert(n >= 0);
|
||||
if (num == n) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Call the destructors on newly hidden elements if there are any
|
||||
for (int i = num; i < oldNum; ++i) {
|
||||
(data + i)->~T();
|
||||
}
|
||||
int oldNum = num;
|
||||
num = n;
|
||||
|
||||
// Once allocated, always maintain 10 elements or 32 bytes, whichever is higher.
|
||||
static const int minSize = iMax(10, 32 / sizeof(T));
|
||||
// Call the destructors on newly hidden elements if there are any
|
||||
for (int i = num; i < oldNum; ++i) {
|
||||
(data + i)->~T();
|
||||
}
|
||||
|
||||
// Once allocated, always maintain MIN_ELEMENTS elements or 32 bytes, whichever is higher.
|
||||
const int minSize = std::max(MIN_ELEMENTS, (int)(MIN_BYTES / sizeof(T)));
|
||||
|
||||
if (num > numAllocated) {
|
||||
if ((MIN_ELEMENTS == 0) && (MIN_BYTES == 0) && (n == 0) && shrinkIfNecessary) {
|
||||
// Deallocate the array completely
|
||||
numAllocated = 0;
|
||||
m_memoryManager->free(data);
|
||||
data = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (num > numAllocated) {
|
||||
// Grow the underlying array
|
||||
|
||||
if (numAllocated == 0) {
|
||||
|
|
@ -382,7 +452,7 @@ public:
|
|||
|
||||
float growFactor = 3.0;
|
||||
|
||||
size_t oldSizeBytes = numAllocated * sizeof(T);
|
||||
int oldSizeBytes = numAllocated * sizeof(T);
|
||||
if (oldSizeBytes > 400000) {
|
||||
// Avoid bloat
|
||||
growFactor = 1.5;
|
||||
|
|
@ -447,6 +517,8 @@ public:
|
|||
|
||||
inline void append(const T& v1, const T& v2) {
|
||||
if (inArray(&v1) || inArray(&v2)) {
|
||||
// Copy into temporaries so that the references won't break when
|
||||
// the array resizes.
|
||||
T t1 = v1;
|
||||
T t2 = v2;
|
||||
append(t1, t2);
|
||||
|
|
@ -457,6 +529,7 @@ public:
|
|||
new (data + num + 1) T(v2);
|
||||
num += 2;
|
||||
} else {
|
||||
// Resize the array. Note that neither value is already in the array.
|
||||
resize(num + 2, DONT_SHRINK_UNDERLYING_ARRAY);
|
||||
data[num - 2] = v1;
|
||||
data[num - 1] = v2;
|
||||
|
|
@ -597,6 +670,24 @@ public:
|
|||
return (*this)[0];
|
||||
}
|
||||
|
||||
/**
|
||||
"The member function returns a reference to the last element of the controlled sequence,
|
||||
which must be non-empty."
|
||||
For compatibility with std::vector.
|
||||
*/
|
||||
T& back() {
|
||||
return (*this)[size()-1];
|
||||
}
|
||||
|
||||
/**
|
||||
"The member function returns a reference to the last element of the controlled sequence,
|
||||
which must be non-empty."
|
||||
For compatibility with std::vector.
|
||||
*/
|
||||
const T& back() const {
|
||||
return (*this)[size()-1];
|
||||
}
|
||||
|
||||
/**
|
||||
Removes the last element and returns it. By default, shrinks the underlying array.
|
||||
*/
|
||||
|
|
@ -638,7 +729,7 @@ public:
|
|||
}
|
||||
|
||||
inline T& operator[](unsigned int n) {
|
||||
debugAssertM(((int)n < num), format("Array index out of bounds. n = %d, size() = %d", n, num));
|
||||
debugAssertM(n < (unsigned int)num, format("Array index out of bounds. n = %d, size() = %d", n, num));
|
||||
return data[n];
|
||||
}
|
||||
|
||||
|
|
@ -737,6 +828,19 @@ public:
|
|||
resize(0);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the index of (the first occurance of) an index or -1 if
|
||||
not found. Searches from the right.
|
||||
*/
|
||||
int rfindIndex(const T& value) const {
|
||||
for (int i = num -1 ; i >= 0; --i) {
|
||||
if (data[i] == value) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the index of (the first occurance of) an index or -1 if
|
||||
not found.
|
||||
|
|
@ -827,12 +931,26 @@ public:
|
|||
return elem1->x < elem2->x;
|
||||
}
|
||||
</PRE>
|
||||
|
||||
or a functor, e.g.,
|
||||
<pre>
|
||||
bool
|
||||
less_than_functor::operator()( const double& lhs, const double& rhs ) const
|
||||
{
|
||||
return( lhs < rhs? true : false );
|
||||
}
|
||||
</pre>
|
||||
*/
|
||||
void sort(bool (__cdecl *lessThan)(const T& elem1, const T& elem2)) {
|
||||
// void sort(bool (__cdecl *lessThan)(const T& elem1, const T& elem2)) {
|
||||
// std::sort(data, data + num, lessThan);
|
||||
//}
|
||||
template<class LessThan>
|
||||
void sort(const LessThan& lessThan) {
|
||||
// Using std::sort, which according to http://www.open-std.org/JTC1/SC22/WG21/docs/D_4.cpp
|
||||
// was 2x faster than qsort for arrays around size 2000 on intel core2 with gcc
|
||||
std::sort(data, data + num, lessThan);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Sorts the array in increasing order using the > or < operator. To
|
||||
invoke this method on Array<T>, T must override those operator.
|
||||
|
|
@ -1149,8 +1267,8 @@ template<class T> bool contains(const T* array, int len, const T& e) {
|
|||
|
||||
} // namespace
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning (pop)
|
||||
#endif
|
||||
|
||||
#ifdef G3D_WIN32
|
||||
# pragma warning (push)
|
||||
#endif
|
||||
|
|
|
|||
164
dep/include/g3dlite/G3D/AtomicInt32.h
Normal file
164
dep/include/g3dlite/G3D/AtomicInt32.h
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
/**
|
||||
@file AtomicInt32.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2005-09-01
|
||||
@edited 2006-06-21
|
||||
*/
|
||||
#ifndef G3D_ATOMICINT32_H
|
||||
#define G3D_ATOMICINT32_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
|
||||
#if defined(G3D_OSX)
|
||||
# include <libkern/OSAtomic.h>
|
||||
#endif
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
An integer that may safely be used on different threads without
|
||||
external locking.
|
||||
|
||||
On Win32, Linux, FreeBSD, and Mac OS X this is implemented without locks.
|
||||
|
||||
<B>BETA API</B> This is unsupported and may change
|
||||
*/
|
||||
class AtomicInt32 {
|
||||
private:
|
||||
# if defined(G3D_WIN32)
|
||||
volatile long m_value;
|
||||
# elif defined(G3D_OSX)
|
||||
int32_t m_value;
|
||||
# else
|
||||
volatile int32 m_value;
|
||||
# endif
|
||||
|
||||
|
||||
public:
|
||||
|
||||
/** Initial value is undefined. */
|
||||
AtomicInt32() {}
|
||||
|
||||
/** Atomic set */
|
||||
explicit AtomicInt32(const int32 x) {
|
||||
m_value = x;
|
||||
}
|
||||
|
||||
/** Atomic set */
|
||||
AtomicInt32(const AtomicInt32& x) {
|
||||
m_value = x.m_value;
|
||||
}
|
||||
|
||||
/** Atomic set */
|
||||
const AtomicInt32& operator=(const int32 x) {
|
||||
m_value = x;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Atomic set */
|
||||
void operator=(const AtomicInt32& x) {
|
||||
m_value = x.m_value;
|
||||
}
|
||||
|
||||
/** Returns the current value */
|
||||
int32 value() const {
|
||||
return m_value;
|
||||
}
|
||||
|
||||
/** Returns the old value, before the add. */
|
||||
int32 add(const int32 x) {
|
||||
# if defined(G3D_WIN32)
|
||||
|
||||
return InterlockedExchangeAdd(&m_value, x);
|
||||
|
||||
# elif defined(G3D_LINUX) || defined(G3D_FREEBSD)
|
||||
|
||||
int32 old;
|
||||
asm volatile ("lock; xaddl %0,%1"
|
||||
: "=r"(old), "=m"(m_value) /* outputs */
|
||||
: "0"(x), "m"(m_value) /* inputs */
|
||||
: "memory", "cc");
|
||||
return old;
|
||||
|
||||
# elif defined(G3D_OSX)
|
||||
|
||||
int32 old = m_value;
|
||||
OSAtomicAdd32(x, &m_value);
|
||||
return old;
|
||||
|
||||
# endif
|
||||
}
|
||||
|
||||
/** Returns old value. */
|
||||
int32 sub(const int32 x) {
|
||||
return add(-x);
|
||||
}
|
||||
|
||||
void increment() {
|
||||
# if defined(G3D_WIN32)
|
||||
// Note: returns the newly incremented value
|
||||
InterlockedIncrement(&m_value);
|
||||
# elif defined(G3D_LINUX) || defined(G3D_FREEBSD)
|
||||
add(1);
|
||||
# elif defined(G3D_OSX)
|
||||
// Note: returns the newly incremented value
|
||||
OSAtomicIncrement32(&m_value);
|
||||
# endif
|
||||
}
|
||||
|
||||
/** Returns zero if the result is zero after decrement, non-zero otherwise.*/
|
||||
int32 decrement() {
|
||||
# if defined(G3D_WIN32)
|
||||
// Note: returns the newly decremented value
|
||||
return InterlockedDecrement(&m_value);
|
||||
# elif defined(G3D_LINUX) || defined(G3D_FREEBSD)
|
||||
unsigned char nz;
|
||||
|
||||
asm volatile ("lock; decl %1;\n\t"
|
||||
"setnz %%al"
|
||||
: "=a" (nz)
|
||||
: "m" (m_value)
|
||||
: "memory", "cc");
|
||||
return nz;
|
||||
# elif defined(G3D_OSX)
|
||||
// Note: returns the newly decremented value
|
||||
return OSAtomicDecrement32(&m_value);
|
||||
# endif
|
||||
}
|
||||
|
||||
|
||||
/** Atomic test-and-set: if <code>*this == comperand</code> then <code>*this := exchange</code> else do nothing.
|
||||
In both cases, returns the old value of <code>*this</code>.
|
||||
|
||||
Performs an atomic comparison of this with the Comperand value.
|
||||
If this is equal to the Comperand value, the Exchange value is stored in this.
|
||||
Otherwise, no operation is performed.
|
||||
|
||||
Under VC6 the sign bit may be lost.
|
||||
*/
|
||||
int32 compareAndSet(const int32 comperand, const int32 exchange) {
|
||||
# if defined(G3D_WIN32)
|
||||
return InterlockedCompareExchange(&m_value, exchange, comperand);
|
||||
# elif defined(G3D_LINUX) || defined(G3D_FREEBSD) || defined(G3D_OSX)
|
||||
// Based on Apache Portable Runtime
|
||||
// http://koders.com/c/fid3B6631EE94542CDBAA03E822CA780CBA1B024822.aspx
|
||||
int32 ret;
|
||||
asm volatile ("lock; cmpxchgl %1, %2"
|
||||
: "=a" (ret)
|
||||
: "r" (exchange), "m" (m_value), "0"(comperand)
|
||||
: "memory", "cc");
|
||||
return ret;
|
||||
|
||||
// Note that OSAtomicCompareAndSwap32 does not return a useful value for us
|
||||
// so it can't satisfy the cmpxchgl contract.
|
||||
# endif
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
140
dep/include/g3dlite/G3D/BinaryFormat.h
Normal file
140
dep/include/g3dlite/G3D/BinaryFormat.h
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
/**
|
||||
@file BinaryFormat.h
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@author 2005-06-03
|
||||
@edited 2005-06-03
|
||||
|
||||
Copyright 2000-2005, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_BINARYFORMAT_H
|
||||
#define G3D_BINARYFORMAT_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
class Vector2;
|
||||
class Vector2int16;
|
||||
class Vector3;
|
||||
class Vector3int16;
|
||||
class Vector4;
|
||||
class Vector4int16;
|
||||
class Color3;
|
||||
class Color3uint8;
|
||||
class Color4;
|
||||
class Color4uint8;
|
||||
|
||||
/**
|
||||
Some values like float16 and int128 have no current CPU data structure that implements them but are useful
|
||||
for file formats and for GPUs.
|
||||
|
||||
CHUNK_BINFMT data follows the protocol.
|
||||
*/
|
||||
// Must be packed int 16 bits for the chunk reader
|
||||
// We can't name these just "INT8" etc. because some libraries #define names like that
|
||||
enum BinaryFormat {
|
||||
FIRST_BINFMT = 1000,
|
||||
|
||||
BOOL8_BINFMT,
|
||||
UINT8_BINFMT, INT8_BINFMT, UINT16_BINFMT, INT16_BINFMT, UINT32_BINFMT, INT32_BINFMT, UINT64_BINFMT, INT64_BINFMT, UINT128_BINFMT, INT128_BINFMT,
|
||||
FLOAT16_BINFMT, FLOAT32_BINFMT, FLOAT64_BINFMT,
|
||||
VECTOR2_BINFMT, VECTOR2INT16_BINFMT,
|
||||
VECTOR3_BINFMT, VECTOR3INT16_BINFMT,
|
||||
VECTOR4_BINFMT, VECTOR4INT16_BINFMT,
|
||||
COLOR3_BINFMT, COLOR3UINT8_BINFMT, COLOR3INT16_BINFMT,
|
||||
COLOR4_BINFMT, COLOR4UINT8_BINFMT, COLOR4INT16_BINFMT,
|
||||
STRING_BINFMT, STRINGEVEN_BINFMT, STRING8_BINFMT, STRING16_BINFMT, STRING32_BINFMT,
|
||||
|
||||
CHUNK_BINFMT,
|
||||
|
||||
CUSTOM_BINFMT,
|
||||
|
||||
LAST_BINFMT
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/** A macro that maps G3D types to format constants.
|
||||
(e.g. binaryFormatOf(Vector3) == VECTOR3_BINFMT).
|
||||
*/
|
||||
// This implementation is designed to meet the following constraints:
|
||||
// 1. Work around the many MSVC++ partial template bugs
|
||||
// 2. Work for primitive types (e.g. int)
|
||||
#define binaryFormatOf(T) (G3D::_internal::_BinaryFormat<T>::x())
|
||||
|
||||
namespace G3D {
|
||||
namespace _internal {
|
||||
|
||||
|
||||
template<class T> class _BinaryFormat {
|
||||
public:
|
||||
static BinaryFormat x() {
|
||||
return CUSTOM_BINFMT;
|
||||
}
|
||||
};
|
||||
}}
|
||||
|
||||
|
||||
/**
|
||||
Macro to declare the underlying format (as will be returned by glFormatOf)
|
||||
of a type. For example,
|
||||
|
||||
<PRE>
|
||||
DECLARE_BINARYFORMATOF(Vector4, VECTOR4_BINFMT)
|
||||
</PRE>
|
||||
|
||||
Use this so you can make vertex arrays of your own classes and not just
|
||||
the standard ones.
|
||||
*/
|
||||
#define DECLARE_BINARYFORMATOF(CType, EnumType) \
|
||||
namespace G3D { \
|
||||
namespace _internal { \
|
||||
template<> class _BinaryFormat<CType> { \
|
||||
public: \
|
||||
static BinaryFormat x() { \
|
||||
return EnumType; \
|
||||
} \
|
||||
}; \
|
||||
} \
|
||||
}
|
||||
|
||||
DECLARE_BINARYFORMATOF( bool, BOOL8_BINFMT )
|
||||
|
||||
DECLARE_BINARYFORMATOF( uint8, UINT8_BINFMT )
|
||||
DECLARE_BINARYFORMATOF( int8, INT8_BINFMT )
|
||||
DECLARE_BINARYFORMATOF( uint16, UINT16_BINFMT )
|
||||
DECLARE_BINARYFORMATOF( int16, INT16_BINFMT )
|
||||
DECLARE_BINARYFORMATOF( uint32, UINT32_BINFMT )
|
||||
DECLARE_BINARYFORMATOF( int32, INT32_BINFMT )
|
||||
DECLARE_BINARYFORMATOF( uint64, UINT64_BINFMT )
|
||||
DECLARE_BINARYFORMATOF( int64, INT64_BINFMT )
|
||||
|
||||
DECLARE_BINARYFORMATOF( float32, FLOAT32_BINFMT )
|
||||
DECLARE_BINARYFORMATOF( float64, FLOAT64_BINFMT )
|
||||
|
||||
DECLARE_BINARYFORMATOF( Vector2, VECTOR2_BINFMT )
|
||||
DECLARE_BINARYFORMATOF( Vector2int16, VECTOR2INT16_BINFMT )
|
||||
DECLARE_BINARYFORMATOF( Vector3, VECTOR3_BINFMT )
|
||||
DECLARE_BINARYFORMATOF( Vector3int16, VECTOR3INT16_BINFMT )
|
||||
DECLARE_BINARYFORMATOF( Vector4, VECTOR4_BINFMT )
|
||||
DECLARE_BINARYFORMATOF( Vector4int16, VECTOR4INT16_BINFMT )
|
||||
|
||||
DECLARE_BINARYFORMATOF( Color3, COLOR3_BINFMT )
|
||||
DECLARE_BINARYFORMATOF( Color3uint8, COLOR3UINT8_BINFMT )
|
||||
DECLARE_BINARYFORMATOF( Color4, COLOR4_BINFMT )
|
||||
DECLARE_BINARYFORMATOF( Color4uint8, COLOR4UINT8_BINFMT )
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/** Returns -1 if the format is custom, otherwise the byte size
|
||||
of a single element in this format.*/
|
||||
int32 byteSize(BinaryFormat f);
|
||||
|
||||
|
||||
} //G3D
|
||||
|
||||
#endif
|
||||
441
dep/include/g3dlite/G3D/BinaryInput.h
Normal file
441
dep/include/g3dlite/G3D/BinaryInput.h
Normal file
|
|
@ -0,0 +1,441 @@
|
|||
/**
|
||||
@file BinaryInput.h
|
||||
|
||||
@maintainer Morgan McGuire, graphics3d.com
|
||||
|
||||
@created 2001-08-09
|
||||
@edited 2006-07-19
|
||||
|
||||
Copyright 2000-2009, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_BinaryInput_h
|
||||
#define G3D_BinaryInput_h
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Disable conditional expression is constant, which occurs incorrectly on inlined functions
|
||||
# pragma warning(push)
|
||||
# pragma warning( disable : 4127 )
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Array.h"
|
||||
#include "G3D/Color4.h"
|
||||
#include "G3D/Color3.h"
|
||||
#include "G3D/Vector4.h"
|
||||
#include "G3D/Vector3.h"
|
||||
#include "G3D/Vector2.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/debug.h"
|
||||
#include "G3D/System.h"
|
||||
|
||||
|
||||
namespace G3D {
|
||||
|
||||
#if defined(G3D_WIN32) || defined(G3D_LINUX)
|
||||
// Allow writing of integers to non-word aligned locations.
|
||||
// This is legal on x86, but not on other platforms.
|
||||
#define G3D_ALLOW_UNALIGNED_WRITES
|
||||
#endif
|
||||
|
||||
/**
|
||||
Sequential or random access byte-order independent binary file access.
|
||||
Files compressed with zlib and beginning with an unsigned 32-bit int
|
||||
size are transparently decompressed when the compressed = true flag is
|
||||
specified to the constructor.
|
||||
|
||||
For every readX method there are also versions that operate on a whole
|
||||
Array, std::vector, or C-array. e.g. readFloat32(Array<float32>& array, n)
|
||||
These methods resize the array or std::vector to the appropriate size
|
||||
before reading. For a C-array, they require the pointer to reference
|
||||
a memory block at least large enough to hold <I>n</I> elements.
|
||||
|
||||
Most classes define serialize/deserialize methods that use BinaryInput,
|
||||
BinaryOutput, TextInput, and TextOutput. There are text serializer
|
||||
functions for primitive types (e.g. int, std::string, float, double) but not
|
||||
binary serializers-- you <B>must</b> call the BinaryInput::readInt32 or
|
||||
other appropriate function. This is because it would be very hard to
|
||||
debug the error sequence: <CODE>serialize(1.0, bo); ... float f; deserialize(f, bi);</CODE>
|
||||
in which a double is serialized and then deserialized as a float.
|
||||
*/
|
||||
class BinaryInput {
|
||||
private:
|
||||
|
||||
// The initial buffer will be no larger than this, but
|
||||
// may grow if a large memory read occurs. 50 MB
|
||||
enum {INITIAL_BUFFER_LENGTH = 50000000};
|
||||
|
||||
/**
|
||||
is the file big or little endian
|
||||
*/
|
||||
G3DEndian m_fileEndian;
|
||||
std::string m_filename;
|
||||
|
||||
bool m_swapBytes;
|
||||
|
||||
/** Next position to read from in bitString during readBits. */
|
||||
int m_bitPos;
|
||||
|
||||
/** Bits currently being read by readBits.
|
||||
Contains at most 8 (low) bits. Note that
|
||||
beginBits/readBits actually consumes one extra byte, which
|
||||
will be restored by writeBits.*/
|
||||
uint32 m_bitString;
|
||||
|
||||
/** 1 when between beginBits and endBits, 0 otherwise. */
|
||||
int m_beginEndBits;
|
||||
|
||||
/** When operating on huge files, we cannot load the whole file into memory.
|
||||
This is the file position to which buffer[0] corresponds.
|
||||
*/
|
||||
int64 m_alreadyRead;
|
||||
|
||||
/**
|
||||
Length of the entire file, in bytes.
|
||||
For the length of the buffer, see bufferLength
|
||||
*/
|
||||
int64 m_length;
|
||||
|
||||
/** Length of the array referenced by buffer. May go past the end of the file!*/
|
||||
int64 m_bufferLength;
|
||||
uint8* m_buffer;
|
||||
|
||||
/**
|
||||
Next byte in file, relative to buffer.
|
||||
*/
|
||||
int64 m_pos;
|
||||
|
||||
/**
|
||||
When true, the buffer is freed in the destructor.
|
||||
*/
|
||||
bool m_freeBuffer;
|
||||
|
||||
/** Ensures that we are able to read at least minLength from startPosition (relative
|
||||
to start of file). */
|
||||
void loadIntoMemory(int64 startPosition, int64 minLength = 0);
|
||||
|
||||
/** Verifies that at least this number of bytes can be read.*/
|
||||
inline void prepareToRead(int64 nbytes) {
|
||||
debugAssertM(m_length > 0, m_filename + " not found or corrupt.");
|
||||
debugAssertM(m_pos + nbytes + m_alreadyRead <= m_length, "Read past end of file.");
|
||||
|
||||
if (m_pos + nbytes > m_bufferLength) {
|
||||
loadIntoMemory(m_pos + m_alreadyRead, nbytes);
|
||||
}
|
||||
}
|
||||
|
||||
// Not implemented on purpose, don't use
|
||||
BinaryInput(const BinaryInput&);
|
||||
BinaryInput& operator=(const BinaryInput&);
|
||||
bool operator==(const BinaryInput&);
|
||||
|
||||
/** Buffer is compressed; replace it with a decompressed version */
|
||||
void decompress();
|
||||
public:
|
||||
|
||||
/** false, constant to use with the copyMemory option */
|
||||
static const bool NO_COPY;
|
||||
|
||||
/**
|
||||
If the file cannot be opened, a zero length buffer is presented.
|
||||
Automatically opens files that are inside zipfiles.
|
||||
|
||||
@param compressed Set to true if and only if the file was
|
||||
compressed using BinaryOutput's zlib compression. This has
|
||||
nothing to do with whether the input is in a zipfile.
|
||||
*/
|
||||
BinaryInput(
|
||||
const std::string& filename,
|
||||
G3DEndian fileEndian,
|
||||
bool compressed = false);
|
||||
|
||||
/**
|
||||
Creates input stream from an in memory source.
|
||||
Unless you specify copyMemory = false, the data is copied
|
||||
from the pointer, so you may deallocate it as soon as the
|
||||
object is constructed. It is an error to specify copyMemory = false
|
||||
and compressed = true.
|
||||
|
||||
To decompress part of a file, you can follow the following paradigm:
|
||||
|
||||
<PRE>
|
||||
BinaryInput master(...);
|
||||
|
||||
// read from master to point where compressed data exists.
|
||||
|
||||
BinaryInput subset(master.getCArray() + master.getPosition(),
|
||||
master.length() - master.getPosition(),
|
||||
master.endian(), true, true);
|
||||
|
||||
// Now read from subset (it is ok for master to go out of scope)
|
||||
</PRE>
|
||||
*/
|
||||
BinaryInput(
|
||||
const uint8* data,
|
||||
int64 dataLen,
|
||||
G3DEndian dataEndian,
|
||||
bool compressed = false,
|
||||
bool copyMemory = true);
|
||||
|
||||
virtual ~BinaryInput();
|
||||
|
||||
/** Change the endian-ness of the file. This only changes the
|
||||
interpretation of the file for future read calls; the
|
||||
underlying data is unmodified.*/
|
||||
void setEndian(G3DEndian endian);
|
||||
|
||||
G3DEndian endian() const {
|
||||
return m_fileEndian;
|
||||
}
|
||||
|
||||
std::string getFilename() const {
|
||||
return m_filename;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a pointer to the internal memory buffer.
|
||||
May throw an exception for huge files.
|
||||
*/
|
||||
const uint8* getCArray() const {
|
||||
if (m_alreadyRead > 0) {
|
||||
throw "Cannot getCArray for a huge file";
|
||||
}
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
Performs bounds checks in debug mode. [] are relative to
|
||||
the start of the file, not the current position.
|
||||
Seeks to the new position before reading (and leaves
|
||||
that as the current position)
|
||||
*/
|
||||
inline uint8 operator[](int64 n) {
|
||||
setPosition(n);
|
||||
return readUInt8();
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the length of the file in bytes.
|
||||
*/
|
||||
inline int64 getLength() const {
|
||||
return m_length;
|
||||
}
|
||||
|
||||
inline int64 size() const {
|
||||
return getLength();
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the current byte position in the file,
|
||||
where 0 is the beginning and getLength() - 1 is the end.
|
||||
*/
|
||||
inline int64 getPosition() const {
|
||||
return m_pos + m_alreadyRead;
|
||||
}
|
||||
|
||||
/**
|
||||
Sets the position. Cannot set past length.
|
||||
May throw a char* when seeking backwards more than 10 MB on a huge file.
|
||||
*/
|
||||
inline void setPosition(int64 p) {
|
||||
debugAssertM(p <= m_length, "Read past end of file");
|
||||
m_pos = p - m_alreadyRead;
|
||||
if ((m_pos < 0) || (m_pos > m_bufferLength)) {
|
||||
loadIntoMemory(m_pos + m_alreadyRead);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Goes back to the beginning of the file.
|
||||
*/
|
||||
inline void reset() {
|
||||
setPosition(0);
|
||||
}
|
||||
|
||||
inline int8 readInt8() {
|
||||
prepareToRead(1);
|
||||
return m_buffer[m_pos++];
|
||||
}
|
||||
|
||||
inline bool readBool8() {
|
||||
return (readInt8() != 0);
|
||||
}
|
||||
|
||||
inline uint8 readUInt8() {
|
||||
prepareToRead(1);
|
||||
return ((uint8*)m_buffer)[m_pos++];
|
||||
}
|
||||
|
||||
uint16 inline readUInt16() {
|
||||
prepareToRead(2);
|
||||
|
||||
m_pos += 2;
|
||||
if (m_swapBytes) {
|
||||
uint8 out[2];
|
||||
out[0] = m_buffer[m_pos - 1];
|
||||
out[1] = m_buffer[m_pos - 2];
|
||||
return *(uint16*)out;
|
||||
} else {
|
||||
#ifdef G3D_ALLOW_UNALIGNED_WRITES
|
||||
return *(uint16*)(&m_buffer[m_pos - 2]);
|
||||
#else
|
||||
uint8 out[2];
|
||||
out[0] = m_buffer[m_pos - 2];
|
||||
out[1] = m_buffer[m_pos - 1];
|
||||
return *(uint16*)out;
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
inline int16 readInt16() {
|
||||
uint16 a = readUInt16();
|
||||
return *(int16*)&a;
|
||||
}
|
||||
|
||||
inline uint32 readUInt32() {
|
||||
prepareToRead(4);
|
||||
|
||||
m_pos += 4;
|
||||
if (m_swapBytes) {
|
||||
uint8 out[4];
|
||||
out[0] = m_buffer[m_pos - 1];
|
||||
out[1] = m_buffer[m_pos - 2];
|
||||
out[2] = m_buffer[m_pos - 3];
|
||||
out[3] = m_buffer[m_pos - 4];
|
||||
return *(uint32*)out;
|
||||
} else {
|
||||
#ifdef G3D_ALLOW_UNALIGNED_WRITES
|
||||
return *(uint32*)(&m_buffer[m_pos - 4]);
|
||||
#else
|
||||
uint8 out[4];
|
||||
out[0] = m_buffer[m_pos - 4];
|
||||
out[1] = m_buffer[m_pos - 3];
|
||||
out[2] = m_buffer[m_pos - 2];
|
||||
out[3] = m_buffer[m_pos - 1];
|
||||
return *(uint32*)out;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline int32 readInt32() {
|
||||
uint32 a = readUInt32();
|
||||
return *(int32*)&a;
|
||||
}
|
||||
|
||||
uint64 readUInt64();
|
||||
|
||||
inline int64 readInt64() {
|
||||
uint64 a = readUInt64();
|
||||
return *(int64*)&a;
|
||||
}
|
||||
|
||||
inline float32 readFloat32() {
|
||||
union {
|
||||
uint32 a;
|
||||
float32 b;
|
||||
};
|
||||
a = readUInt32();
|
||||
return b;
|
||||
}
|
||||
|
||||
inline float64 readFloat64() {
|
||||
union {
|
||||
uint64 a;
|
||||
float64 b;
|
||||
};
|
||||
a = readUInt64();
|
||||
return b;
|
||||
}
|
||||
|
||||
void readBytes(void* bytes, int64 n);
|
||||
|
||||
/**
|
||||
Reads an n character string. The string is not
|
||||
required to end in NULL in the file but will
|
||||
always be a proper std::string when returned.
|
||||
*/
|
||||
std::string readString(int64 n);
|
||||
|
||||
/**
|
||||
Reads until NULL or the end of the file is encountered.
|
||||
*/
|
||||
std::string readString();
|
||||
|
||||
/**
|
||||
Reads until NULL or the end of the file is encountered.
|
||||
If the string has odd length (including NULL), reads
|
||||
another byte.
|
||||
*/
|
||||
std::string readStringEven();
|
||||
|
||||
|
||||
std::string readString32();
|
||||
|
||||
Vector4 readVector4();
|
||||
Vector3 readVector3();
|
||||
Vector2 readVector2();
|
||||
|
||||
Color4 readColor4();
|
||||
Color3 readColor3();
|
||||
|
||||
/**
|
||||
Skips ahead n bytes.
|
||||
*/
|
||||
inline void skip(int64 n) {
|
||||
setPosition(m_pos + m_alreadyRead + n);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns true if the position is not at the end of the file
|
||||
*/
|
||||
inline bool hasMore() const {
|
||||
return m_pos + m_alreadyRead < m_length;
|
||||
}
|
||||
|
||||
/** Prepares for bit reading via readBits. Only readBits can be
|
||||
called between beginBits and endBits without corrupting the
|
||||
data stream. */
|
||||
void beginBits();
|
||||
|
||||
/** Can only be called between beginBits and endBits */
|
||||
uint32 readBits(int numBits);
|
||||
|
||||
/** Ends bit-reading. */
|
||||
void endBits();
|
||||
|
||||
# define DECLARE_READER(ucase, lcase)\
|
||||
void read##ucase(lcase* out, int64 n);\
|
||||
void read##ucase(std::vector<lcase>& out, int64 n);\
|
||||
void read##ucase(Array<lcase>& out, int64 n);
|
||||
|
||||
DECLARE_READER(Bool8, bool)
|
||||
DECLARE_READER(UInt8, uint8)
|
||||
DECLARE_READER(Int8, int8)
|
||||
DECLARE_READER(UInt16, uint16)
|
||||
DECLARE_READER(Int16, int16)
|
||||
DECLARE_READER(UInt32, uint32)
|
||||
DECLARE_READER(Int32, int32)
|
||||
DECLARE_READER(UInt64, uint64)
|
||||
DECLARE_READER(Int64, int64)
|
||||
DECLARE_READER(Float32, float32)
|
||||
DECLARE_READER(Float64, float64)
|
||||
# undef DECLARE_READER
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
421
dep/include/g3dlite/G3D/BinaryOutput.h
Normal file
421
dep/include/g3dlite/G3D/BinaryOutput.h
Normal file
|
|
@ -0,0 +1,421 @@
|
|||
/**
|
||||
@file BinaryOutput.h
|
||||
|
||||
@maintainer Morgan McGuire, graphics3d.com
|
||||
|
||||
@created 2001-08-09
|
||||
@edited 2008-01-24
|
||||
|
||||
Copyright 2000-2006, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_BINARYOUTPUT_H
|
||||
#define G3D_BINARYOUTPUT_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include <assert.h>
|
||||
#include <string>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include "G3D/Color4.h"
|
||||
#include "G3D/Color3.h"
|
||||
#include "G3D/Vector4.h"
|
||||
#include "G3D/Vector3.h"
|
||||
#include "G3D/Vector2.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/debug.h"
|
||||
#include "G3D/BinaryInput.h"
|
||||
#include "G3D/System.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning (push)
|
||||
// Conditional is constant (wrong in inline)
|
||||
# pragma warning (disable : 4127)
|
||||
#endif
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
Sequential or random access byte-order independent binary file access.
|
||||
|
||||
The compress() call can be used to compress with zlib.
|
||||
|
||||
Any method call can trigger an out of memory error (thrown as char*)
|
||||
when writing to "<memory>" instead of a file.
|
||||
|
||||
Compressed writing and seeking backwards is not supported for huge files
|
||||
(i.e., BinaryOutput may have to dump the contents to disk if they
|
||||
exceed available RAM).
|
||||
*/
|
||||
class BinaryOutput {
|
||||
private:
|
||||
std::string m_filename;
|
||||
|
||||
bool m_committed;
|
||||
|
||||
/** 0 outside of beginBits...endBits, 1 inside */
|
||||
int m_beginEndBits;
|
||||
|
||||
/** The current string of bits being built up by beginBits...endBits.
|
||||
This string is treated semantically, as if the lowest bit was
|
||||
on the left and the highest was on the right.*/
|
||||
int8 m_bitString;
|
||||
|
||||
/** Position (from the lowest bit) currently used in bitString.*/
|
||||
int m_bitPos;
|
||||
|
||||
// True if the file endianess does not match the machine endian
|
||||
bool m_swapBytes;
|
||||
|
||||
G3DEndian m_fileEndian;
|
||||
|
||||
uint8* m_buffer;
|
||||
|
||||
/** Size of the elements used */
|
||||
int m_bufferLen;
|
||||
|
||||
/** Underlying size of memory allocaded */
|
||||
int m_maxBufferLen;
|
||||
|
||||
/** Next byte in file */
|
||||
int m_pos;
|
||||
|
||||
/** is this initialized? */
|
||||
bool m_init;
|
||||
|
||||
/** Number of bytes already written to the file.*/
|
||||
size_t m_alreadyWritten;
|
||||
|
||||
bool m_ok;
|
||||
|
||||
void reserveBytesWhenOutOfMemory(size_t bytes);
|
||||
|
||||
void reallocBuffer(size_t bytes, size_t oldBufferLen);
|
||||
|
||||
/**
|
||||
Make sure at least bytes can be written, resizing if
|
||||
necessary.
|
||||
*/
|
||||
inline void reserveBytes(int bytes) {
|
||||
debugAssert(bytes > 0);
|
||||
size_t oldBufferLen = (size_t)m_bufferLen;
|
||||
|
||||
m_bufferLen = iMax(m_bufferLen, (m_pos + bytes));
|
||||
if (m_bufferLen > m_maxBufferLen) {
|
||||
reallocBuffer(bytes, oldBufferLen);
|
||||
}
|
||||
}
|
||||
|
||||
// Not implemented on purpose, don't use
|
||||
BinaryOutput(const BinaryOutput&);
|
||||
BinaryOutput& operator=(const BinaryOutput&);
|
||||
bool operator==(const BinaryOutput&);
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
You must call setEndian() if you use this (memory) constructor.
|
||||
*/
|
||||
BinaryOutput();
|
||||
|
||||
/**
|
||||
Doesn't actually open the file; commit() does that.
|
||||
Use "<memory>" as the filename if you're going to commit
|
||||
to memory.
|
||||
*/
|
||||
BinaryOutput(
|
||||
const std::string& filename,
|
||||
G3DEndian fileEndian);
|
||||
|
||||
~BinaryOutput();
|
||||
|
||||
/** Compresses the data in the buffer in place,
|
||||
preceeding it with a little-endian uint32 indicating
|
||||
the uncompressed size.
|
||||
|
||||
Call immediately before commit().
|
||||
|
||||
Cannot be used for huge files (ones where the data
|
||||
was already written to disk)-- will throw char*.
|
||||
*/
|
||||
void compress();
|
||||
|
||||
/** True if no errors have been encountered.*/
|
||||
bool ok() const;
|
||||
|
||||
/**
|
||||
Returns a pointer to the internal memory buffer.
|
||||
*/
|
||||
inline const uint8* getCArray() const {
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
void setEndian(G3DEndian fileEndian);
|
||||
|
||||
G3DEndian endian() const {
|
||||
return m_fileEndian;
|
||||
}
|
||||
|
||||
std::string getFilename() const {
|
||||
return m_filename;
|
||||
}
|
||||
|
||||
/**
|
||||
Write the bytes to disk. It is ok to call this
|
||||
multiple times; it will just overwrite the previous file.
|
||||
|
||||
Parent directories are created as needed if they do
|
||||
not exist.
|
||||
|
||||
<B>Not</B> called from the destructor; you must call
|
||||
it yourself.
|
||||
|
||||
@param flush If true (default) the file is ready for reading when the method returns, otherwise
|
||||
the method returns immediately and writes the file in the background.
|
||||
*/
|
||||
void commit(bool flush = true);
|
||||
|
||||
/**
|
||||
Write the bytes to memory (which must be of
|
||||
at least size() bytes).
|
||||
*/
|
||||
void commit(uint8*);
|
||||
|
||||
/**
|
||||
A memory BinaryOutput may be reset so that it can be written to again
|
||||
without allocating new memory. The underlying array will not be deallocated,
|
||||
but the reset structure will act like a newly intialized one.
|
||||
*/
|
||||
void reset();
|
||||
|
||||
|
||||
inline int length() const {
|
||||
return (int)m_bufferLen + (int)m_alreadyWritten;
|
||||
}
|
||||
|
||||
inline int size() const {
|
||||
return length();
|
||||
}
|
||||
|
||||
/**
|
||||
Sets the length of the file to n, padding
|
||||
with 0's past the current end. Does not
|
||||
change the position of the next byte to be
|
||||
written unless n < size().
|
||||
|
||||
Throws char* when resetting a huge file to be shorter
|
||||
than its current length.
|
||||
*/
|
||||
inline void setLength(int n) {
|
||||
n = n - (int)m_alreadyWritten;
|
||||
|
||||
if (n < 0) {
|
||||
throw "Cannot resize huge files to be shorter.";
|
||||
}
|
||||
|
||||
if (n < m_bufferLen) {
|
||||
m_pos = n;
|
||||
}
|
||||
if (n > m_bufferLen) {
|
||||
reserveBytes(n - m_bufferLen);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the current byte position in the file,
|
||||
where 0 is the beginning and getLength() - 1 is the end.
|
||||
*/
|
||||
inline int64 position() const {
|
||||
return (int64)m_pos + (int64)m_alreadyWritten;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Sets the position. Can set past length, in which case
|
||||
the file is padded with zeros up to one byte before the
|
||||
next to be written.
|
||||
|
||||
May throw a char* exception when seeking backwards on a huge file.
|
||||
*/
|
||||
inline void setPosition(int64 p) {
|
||||
p = p - (int64)m_alreadyWritten;
|
||||
|
||||
if (p > m_bufferLen) {
|
||||
setLength((int)(p + (int64)m_alreadyWritten));
|
||||
}
|
||||
|
||||
if (p < 0) {
|
||||
throw "Cannot seek more than 10 MB backwards on huge files.";
|
||||
}
|
||||
|
||||
m_pos = (int)p;
|
||||
}
|
||||
|
||||
|
||||
void writeBytes(
|
||||
const void* b,
|
||||
int count) {
|
||||
|
||||
reserveBytes(count);
|
||||
debugAssert(m_pos >= 0);
|
||||
debugAssert(m_bufferLen >= count);
|
||||
System::memcpy(m_buffer + m_pos, b, count);
|
||||
m_pos += count;
|
||||
}
|
||||
|
||||
/**
|
||||
Writes a signed 8-bit integer to the current position.
|
||||
*/
|
||||
inline void writeInt8(int8 i) {
|
||||
reserveBytes(1);
|
||||
m_buffer[m_pos] = *(uint8*)&i;
|
||||
m_pos++;
|
||||
}
|
||||
|
||||
inline void writeBool8(bool b) {
|
||||
writeInt8(b ? 1 : 0);
|
||||
}
|
||||
|
||||
inline void writeUInt8(uint8 i) {
|
||||
reserveBytes(1);
|
||||
m_buffer[m_pos] = i;
|
||||
m_pos++;
|
||||
}
|
||||
|
||||
void writeUInt16(uint16 u);
|
||||
|
||||
inline void writeInt16(int16 i) {
|
||||
writeUInt16(*(uint16*)&i);
|
||||
}
|
||||
|
||||
void writeUInt32(uint32 u);
|
||||
|
||||
inline void writeInt32(int32 i) {
|
||||
debugAssert(m_beginEndBits == 0);
|
||||
writeUInt32(*(uint32*)&i);
|
||||
}
|
||||
|
||||
void writeUInt64(uint64 u);
|
||||
|
||||
inline void writeInt64(int64 i) {
|
||||
writeUInt64(*(uint64*)&i);
|
||||
}
|
||||
|
||||
inline void writeFloat32(float32 f) {
|
||||
debugAssert(m_beginEndBits == 0);
|
||||
union {
|
||||
float32 a;
|
||||
uint32 b;
|
||||
};
|
||||
a = f;
|
||||
writeUInt32(b);
|
||||
}
|
||||
|
||||
inline void writeFloat64(float64 f) {
|
||||
union {
|
||||
float64 a;
|
||||
uint64 b;
|
||||
};
|
||||
a = f;
|
||||
writeUInt64(b);
|
||||
}
|
||||
|
||||
/**
|
||||
Write a string with NULL termination.
|
||||
*/
|
||||
inline void writeString(const std::string& s) {
|
||||
writeString(s.c_str());
|
||||
}
|
||||
|
||||
void writeString(const char* s);
|
||||
|
||||
/**
|
||||
Write a string, ensuring that the total length
|
||||
including NULL is even.
|
||||
*/
|
||||
void writeStringEven(const std::string& s) {
|
||||
writeStringEven(s.c_str());
|
||||
}
|
||||
|
||||
void writeStringEven(const char* s);
|
||||
|
||||
|
||||
void writeString32(const char* s);
|
||||
|
||||
/**
|
||||
Write a string with a 32-bit length field in front
|
||||
of it.
|
||||
*/
|
||||
void writeString32(const std::string& s) {
|
||||
writeString32(s.c_str());
|
||||
}
|
||||
|
||||
void writeVector4(const Vector4& v);
|
||||
|
||||
void writeVector3(const Vector3& v);
|
||||
|
||||
void writeVector2(const Vector2& v);
|
||||
|
||||
void writeColor4(const Color4& v);
|
||||
|
||||
void writeColor3(const Color3& v);
|
||||
|
||||
/**
|
||||
Skips ahead n bytes.
|
||||
*/
|
||||
inline void skip(int n) {
|
||||
if (m_pos + n > m_bufferLen) {
|
||||
setLength((int)m_pos + (int)m_alreadyWritten + n);
|
||||
}
|
||||
m_pos += n;
|
||||
}
|
||||
|
||||
/** Call before a series of BinaryOutput::writeBits calls. Only writeBits
|
||||
can be called between beginBits and endBits without corrupting the stream.*/
|
||||
void beginBits();
|
||||
|
||||
/** Write numBits from bitString to the output stream. Bits are numbered from
|
||||
low to high.
|
||||
|
||||
Can only be
|
||||
called between beginBits and endBits. Bits written are semantically
|
||||
little-endian, regardless of the actual endian-ness of the system. That is,
|
||||
<CODE>writeBits(0xABCD, 16)</CODE> writes 0xCD to the first byte and
|
||||
0xAB to the second byte. However, if used with BinaryInput::readBits, the ordering
|
||||
is transparent to the caller.
|
||||
*/
|
||||
void writeBits(uint32 bitString, int numBits);
|
||||
|
||||
/** Call after a series of BinaryOutput::writeBits calls. This will
|
||||
finish out with zeros the last byte into which bits were written.*/
|
||||
void endBits();
|
||||
|
||||
|
||||
# define DECLARE_WRITER(ucase, lcase)\
|
||||
void write##ucase(const lcase* out, int n);\
|
||||
void write##ucase(const std::vector<lcase>& out, int n);\
|
||||
void write##ucase(const Array<lcase>& out, int n);
|
||||
|
||||
DECLARE_WRITER(Bool8, bool)
|
||||
DECLARE_WRITER(UInt8, uint8)
|
||||
DECLARE_WRITER(Int8, int8)
|
||||
DECLARE_WRITER(UInt16, uint16)
|
||||
DECLARE_WRITER(Int16, int16)
|
||||
DECLARE_WRITER(UInt32, uint32)
|
||||
DECLARE_WRITER(Int32, int32)
|
||||
DECLARE_WRITER(UInt64, uint64)
|
||||
DECLARE_WRITER(Int64, int64)
|
||||
DECLARE_WRITER(Float32, float32)
|
||||
DECLARE_WRITER(Float64, float64)
|
||||
# undef DECLARE_WRITER
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning (pop)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
20
dep/include/g3dlite/G3D/BoundsTrait.h
Normal file
20
dep/include/g3dlite/G3D/BoundsTrait.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/**
|
||||
@file BoundsTrait.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
@created 2008-10-01
|
||||
@edited 2008-10-01
|
||||
Copyright 2000-2009, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_BOUNDSTRAIT_H
|
||||
#define G3D_BOUNDSTRAIT_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
|
||||
template<typename Value>
|
||||
struct BoundsTrait{};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -3,11 +3,11 @@
|
|||
|
||||
Box class
|
||||
|
||||
@maintainer Morgan McGuire, matrix@graphics3d.com
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@cite Portions based on Dave Eberly's Magic Software Library at <A HREF="http://www.magic-software.com">http://www.magic-software.com</A>
|
||||
@created 2001-06-02
|
||||
@edited 2006-01-05
|
||||
@edited 2007-06-05
|
||||
|
||||
Copyright 2000-2006, Morgan McGuire.
|
||||
All rights reserved.
|
||||
|
|
@ -84,8 +84,14 @@ public:
|
|||
const Vector3& min,
|
||||
const Vector3& max);
|
||||
|
||||
static Box inf();
|
||||
|
||||
Box(class BinaryInput& b);
|
||||
|
||||
Box(const class AABox& b);
|
||||
|
||||
void serialize(class BinaryOutput& b) const;
|
||||
void deserialize(class BinaryInput& b);
|
||||
|
||||
/**
|
||||
Returns the object to world transformation for
|
||||
|
|
@ -105,18 +111,6 @@ public:
|
|||
return _center;
|
||||
}
|
||||
|
||||
inline Vector3 getCenter() const {
|
||||
return center();
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a corner (0 <= i < 8)
|
||||
@deprecated
|
||||
*/
|
||||
inline Vector3 getCorner(int i) const {
|
||||
debugAssert(i < 8);
|
||||
return _corner[i];
|
||||
}
|
||||
|
||||
inline Vector3 corner(int i) const {
|
||||
debugAssert(i < 8);
|
||||
|
|
@ -155,65 +149,34 @@ public:
|
|||
Vector3& v2,
|
||||
Vector3& v3) const;
|
||||
|
||||
/**
|
||||
@deprecated Use culledBy(Array<Plane>&)
|
||||
*/
|
||||
bool culledBy(
|
||||
const class Plane* plane,
|
||||
int numPlanes,
|
||||
int32& cullingPlaneIndex,
|
||||
const uint32 testMask,
|
||||
uint32& childMask) const;
|
||||
|
||||
/**
|
||||
@deprecated Use culledBy(Array<Plane>&)
|
||||
*/
|
||||
bool culledBy(
|
||||
const class Plane* plane,
|
||||
int numPlanes,
|
||||
int32& cullingPlaneIndex = dummy,
|
||||
const uint32 testMask = -1) const;
|
||||
|
||||
/**
|
||||
See AABox::culledBy
|
||||
*/
|
||||
bool culledBy(
|
||||
const Array<Plane>& plane,
|
||||
int32& cullingPlaneIndex,
|
||||
const uint32 testMask,
|
||||
uint32& childMask) const;
|
||||
bool culledBy
|
||||
(
|
||||
const Array<Plane>& plane,
|
||||
int32& cullingPlaneIndex,
|
||||
const uint32 testMask,
|
||||
uint32& childMask) const;
|
||||
|
||||
/**
|
||||
Conservative culling test that does not produce a mask for children.
|
||||
*/
|
||||
bool culledBy(
|
||||
const Array<Plane>& plane,
|
||||
int32& cullingPlaneIndex = dummy,
|
||||
const uint32 testMask = -1) const;
|
||||
bool culledBy
|
||||
(
|
||||
const Array<Plane>& plane,
|
||||
int32& cullingPlaneIndex = dummy,
|
||||
const uint32 testMask = -1) const;
|
||||
|
||||
bool contains(
|
||||
const Vector3& point) const;
|
||||
|
||||
/** @deprecated */
|
||||
float surfaceArea() const;
|
||||
|
||||
inline float area() const {
|
||||
return surfaceArea();
|
||||
}
|
||||
float area() const;
|
||||
|
||||
float volume() const;
|
||||
|
||||
void getRandomSurfacePoint(Vector3& P, Vector3& N = Vector3::dummy) const;
|
||||
|
||||
/**
|
||||
@deprecated
|
||||
Uniformly distributed on the surface.
|
||||
*/
|
||||
inline Vector3 randomSurfacePoint() const {
|
||||
Vector3 V;
|
||||
getRandomSurfacePoint(V);
|
||||
return V;
|
||||
}
|
||||
void getRandomSurfacePoint(Vector3& P, Vector3& N = Vector3::ignore()) const;
|
||||
|
||||
/**
|
||||
Uniformly distributed on the interior (includes surface)
|
||||
|
|
@ -221,6 +184,10 @@ public:
|
|||
Vector3 randomInteriorPoint() const;
|
||||
|
||||
void getBounds(class AABox&) const;
|
||||
|
||||
bool isFinite() const {
|
||||
return G3D::isFinite(_volume);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
121
dep/include/g3dlite/G3D/Box2D.h
Normal file
121
dep/include/g3dlite/G3D/Box2D.h
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
/**
|
||||
@file Box2D.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2001-06-02
|
||||
@edited 2008-12-27
|
||||
|
||||
Copyright 2000-2009, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_Box2D_h
|
||||
#define G3D_Box2D_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Vector2.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
class CoordinateFrame;
|
||||
typedef class CoordinateFrame CFrame;
|
||||
class Rect2D;
|
||||
typedef class Rect2D AABox2D;
|
||||
|
||||
/**
|
||||
2D oriented box
|
||||
@cite http://www.flipcode.com/archives/2D_OBB_Intersection.shtml
|
||||
*/
|
||||
class Box2D {
|
||||
private:
|
||||
/** Corners of the box, where 0 is the lower left. */
|
||||
Vector2 m_corner[4];
|
||||
|
||||
/** Two edges of the box extended away from corner[0], with length
|
||||
= 1 / extentSquared */
|
||||
Vector2 m_axisin[2];
|
||||
|
||||
/** Two edges of the box extended away from corner[0], with unit length */
|
||||
Vector2 m_axis[2];
|
||||
|
||||
/** Centroid of the box */
|
||||
Vector2 m_center;
|
||||
|
||||
/** origin[a] = m_corner[0].dot(m_axisin[a]); */
|
||||
float origin[2];
|
||||
|
||||
/** Surface area */
|
||||
float m_area;
|
||||
|
||||
Vector2 m_extent;
|
||||
|
||||
/** Returns true if other overlaps one dimension of this. */
|
||||
bool overlaps1Way(const Box2D& other) const;
|
||||
|
||||
|
||||
/** Updates the axes after the m_corners move. Assumes the
|
||||
m_corners actually form a rectangle. */
|
||||
void computeAxes();
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
@param center World-space center
|
||||
@param w Width along object-space x-axis
|
||||
@param h Height along object-space y-axis
|
||||
@param angle Counter-clockwise angle from object-space x-axis in radians
|
||||
*/
|
||||
Box2D(const Vector2& center = Vector2(0, 0), float w = 0, float h = 0, float angle = 0);
|
||||
|
||||
Box2D(const AABox2D& b);
|
||||
|
||||
Box2D(const Vector2& min, const Vector2& max);
|
||||
|
||||
/** Transform @a b by @a frame, discarding the Z components, and
|
||||
compute the new box.*/
|
||||
Box2D(const CFrame& frame, Box2D& b);
|
||||
|
||||
inline bool contains(const Vector2& v) const {
|
||||
// Take to object space:
|
||||
const Vector2& p = v - m_center;
|
||||
float x = p.dot(m_axisin[0]);
|
||||
float y = p.dot(m_axisin[1]);
|
||||
|
||||
// Must be within extent/2 on both axes in object space
|
||||
return (abs(x) <= 0.5f) && (abs(y) <= 0.5f);
|
||||
}
|
||||
|
||||
/** @brief Distance from corner(0) to the next corner along the box's local axis a. */
|
||||
inline const Vector2& extent() const {
|
||||
return m_extent;
|
||||
}
|
||||
|
||||
/** @brief Unit length vector along axis @a a */
|
||||
inline const Vector2& axis(int a) const {
|
||||
debugAssert(a == 0 || a == 1);
|
||||
return m_axis[a];
|
||||
}
|
||||
|
||||
/** @brief Surface area */
|
||||
inline float area() const {
|
||||
return m_area;
|
||||
}
|
||||
|
||||
inline const Vector2& corner(int i) const {
|
||||
debugAssert(i >=0 && i <= 3);
|
||||
return m_corner[i];
|
||||
}
|
||||
|
||||
inline const Vector2& center() const {
|
||||
return m_center;
|
||||
}
|
||||
|
||||
/** Returns true if the intersection of the boxes is non-empty. */
|
||||
inline bool overlaps(const Box2D& other) const {
|
||||
return overlaps1Way(other) && other.overlaps1Way(*this);
|
||||
}
|
||||
};
|
||||
|
||||
} // G3D
|
||||
#endif
|
||||
61
dep/include/g3dlite/G3D/BumpMapPreprocess.h
Normal file
61
dep/include/g3dlite/G3D/BumpMapPreprocess.h
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
/**
|
||||
\file BumpMapPreprocess.h
|
||||
|
||||
\maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
\created 2010-01-28
|
||||
\edited 2010-01-28
|
||||
|
||||
Copyright 2000-2010, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_BumpMapPreprocess_h
|
||||
#define G3D_BumpMapPreprocess_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
|
||||
namespace G3D {
|
||||
class Any;
|
||||
|
||||
/**
|
||||
Not in the BumpMap class to avoid a circular dependency between Texture and BumpMap.
|
||||
G3D::GImage::computeNormalMap().
|
||||
*/
|
||||
class BumpMapPreprocess {
|
||||
public:
|
||||
|
||||
/** If true, the elevations are box filtered after computing normals
|
||||
and before uploading, which produces better results for parallax offset mapping
|
||||
Defaults to false. */
|
||||
bool lowPassFilter;
|
||||
|
||||
/** Height of the maximum ("white") value, in pixels, for the purpose of computing normals.
|
||||
A value of 255 means that a 255 x 255 bump image with a full black-to-white gradient
|
||||
will produce a 45-degree ramp (this also results in "cubic" voxels).
|
||||
A negative value means to set zExtentPixels to -zExtentPixels * max(width, height).
|
||||
The default is -0.02.
|
||||
*/
|
||||
float zExtentPixels;
|
||||
|
||||
/** After computing normals, scale the height by |N.z|, a trick that reduces texture swim in steep areas for parallax offset
|
||||
mapping. Defaults to false.*/
|
||||
bool scaleZByNz;
|
||||
|
||||
BumpMapPreprocess() : lowPassFilter(false), zExtentPixels(-0.02f), scaleZByNz(false) {}
|
||||
|
||||
BumpMapPreprocess(const Any& any);
|
||||
|
||||
operator Any() const;
|
||||
|
||||
bool operator==(const BumpMapPreprocess& other) const {
|
||||
return
|
||||
(lowPassFilter == other.lowPassFilter) &&
|
||||
(zExtentPixels == other.zExtentPixels) &&
|
||||
(scaleZByNz == other.scaleZByNz);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
90
dep/include/g3dlite/G3D/Capsule.h
Normal file
90
dep/include/g3dlite/G3D/Capsule.h
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
/**
|
||||
@file Capsule.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2003-02-07
|
||||
@edited 2005-08-20
|
||||
|
||||
Copyright 2000-2006, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_CAPSULE_H
|
||||
#define G3D_CAPSULE_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/Vector3.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
class Line;
|
||||
class AABox;
|
||||
/**
|
||||
A shape formed by extruding a sphere along a line segment.
|
||||
*/
|
||||
class Capsule {
|
||||
private:
|
||||
Vector3 p1;
|
||||
Vector3 p2;
|
||||
|
||||
float _radius;
|
||||
public:
|
||||
|
||||
|
||||
/** Uninitialized */
|
||||
Capsule();
|
||||
Capsule(class BinaryInput& b);
|
||||
Capsule(const Vector3& _p1, const Vector3& _p2, float _r);
|
||||
void serialize(class BinaryOutput& b) const;
|
||||
void deserialize(class BinaryInput& b);
|
||||
|
||||
/** The line down the center of the capsule */
|
||||
Line axis() const;
|
||||
|
||||
inline float radius() const {
|
||||
return _radius;
|
||||
}
|
||||
|
||||
/** Argument may be 0 or 1 */
|
||||
inline Vector3 point(int i) const {
|
||||
debugAssert(i == 0 || i == 1);
|
||||
return (i == 0) ? p1 : p2;
|
||||
}
|
||||
|
||||
/** Distance between the sphere centers. The total extent of the cylinder is
|
||||
2r + h. */
|
||||
inline float height() const {
|
||||
return (p1 - p2).magnitude();
|
||||
}
|
||||
|
||||
inline Vector3 center() const {
|
||||
return (p1 + p2) / 2.0;
|
||||
}
|
||||
|
||||
/** Get a reference frame in which the center of mass is the origin and Y is the axis of the capsule.*/
|
||||
void getReferenceFrame(class CoordinateFrame& cframe) const;
|
||||
|
||||
/**
|
||||
Returns true if the point is inside the capsule or on its surface.
|
||||
*/
|
||||
bool contains(const Vector3& p) const;
|
||||
|
||||
float volume() const;
|
||||
|
||||
float area() const;
|
||||
|
||||
/** Get axis aligned bounding box */
|
||||
void getBounds(AABox& out) const;
|
||||
|
||||
/** Random world space point with outward facing normal. */
|
||||
void getRandomSurfacePoint(Vector3& P, Vector3& N) const;
|
||||
|
||||
/** Point selected uniformly at random over the volume. */
|
||||
Vector3 randomInteriorPoint() const;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
|
|
@ -4,17 +4,18 @@
|
|||
|
||||
Moving collision detection for simple primitives.
|
||||
|
||||
@author Morgan McGuire, matrix@graphics3d.com
|
||||
@author Morgan McGuire, http://graphics.cs.williams.edu
|
||||
@cite Spherical collision based on Paul Nettle's
|
||||
ftp://ftp.3dmaileffects.com/pub/FluidStudios/CollisionDetection/Fluid_Studios_Generic_Collision_Detection_for_Games_Using_Ellipsoids.pdf
|
||||
and comments by Max McGuire. Ray-sphere intersection by Eric Haines.
|
||||
Box-Box intersection written by Kevin Egan.
|
||||
Thanks to Max McGuire of Iron Lore for various bug fixes.
|
||||
Box-Triangle by Tomas Akenine-Moller
|
||||
|
||||
@created 2001-11-19
|
||||
@edited 2006-01-10
|
||||
@edited 2008-12-19
|
||||
|
||||
Copyright 2000-2006, Morgan McGuire.
|
||||
Copyright 2000-2009, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
|
@ -68,17 +69,17 @@ namespace G3D {
|
|||
|
||||
<table>
|
||||
<tr><td></td><td><b>Vector3</b></td><td><b>LineSegment</b></td><td><b>Ray *</b></td><td><b>Line</b></td><td><b>Plane</b></td><td><b>Triangle</b></td><td><b>Sphere</b></td><td><b>Cylinder</b></td><td><b>Capsule</b></td><td><b>AABox</b></td><td><b>Box</b></td></tr>
|
||||
<tr><td><b>Vector3</b></td><td>Vector3::operator== Vector3::fuzzyEq G3D::distance</td><td bgcolor=#C0C0C0 colspan=10 ></td></tr>
|
||||
<tr><td><b>LineSegment</b></td><td>LineSegment::closestPoint LineSegment::distance CollisionDetection::closestPointOnLineSegment</td><td></td><td bgcolor=#C0C0C0 colspan=9 ></td></tr>
|
||||
<tr><td><b>Vector3</b></td><td>\link Vector3::operator== V3::==\endlink \link Vector3::fuzzyEq V3::fuzzy \endlink \link G3D::distance distance \endlink</td><td bgcolor=#C0C0C0 colspan=10 ></td></tr>
|
||||
<tr><td><b>LineSegment</b></td><td>\link LineSegment::closestPoint LS::closestPoint\endlink \link LineSegment::distance LS::distance\endlink \link CollisionDetection::closestPointOnLineSegment CD\endlink</td><td></td><td bgcolor=#C0C0C0 colspan=9 ></td></tr>
|
||||
<tr><td><b>Ray *</b></td><td>Ray::closestPoint Ray::distance</td><td></td><td></td><td bgcolor=#C0C0C0 colspan=8 ></td></tr>
|
||||
<tr><td><b>Line</b></td><td>Line::closestPoint Line::distance</td><td></td><td>CollisionDetection::closestPointsBetweenLineAndLine</td><td></td><td bgcolor=#C0C0C0 colspan=7 ></td></tr>
|
||||
<tr><td><b>Line</b></td><td>Line::closestPoint Line::distance</td><td></td><td>\link CollisionDetection::closestPointsBetweenLineAndLine CD\endlink</td><td></td><td bgcolor=#C0C0C0 colspan=7 ></td></tr>
|
||||
<tr><td><b>Plane</b></td><td></td><td></td><td></td><td></td><td></td><td bgcolor=#C0C0C0 colspan=6 ></td></tr>
|
||||
<tr><td><b>Triangle</b></td><td></td><td></td><td></td><td></td><td></td><td></td><td bgcolor=#C0C0C0 colspan=5 ></td></tr>
|
||||
<tr><td><b>Sphere</b></td><td>Sphere::contains</td><td></td><td></td><td></td><td></td><td></td><td></td><td bgcolor=#C0C0C0 colspan=4 ></td></tr>
|
||||
<tr><td><b>Sphere</b></td><td>Sphere::contains</td><td></td><td>\link CollisionDetection::collisionTimeForMovingPointFixedSphere CD \endlink, \link Ray::intersectionTime R::time\endlink</td><td></td><td></td><td></td><td></td><td bgcolor=#C0C0C0 colspan=4 ></td></tr>
|
||||
<tr><td><b>Cylinder</b></td><td>Cylinder::contains</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td bgcolor=#C0C0C0 colspan=3 ></td></tr>
|
||||
<tr><td><b>Capsule</b></td><td>Capsule::contains</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td bgcolor=#C0C0C0 colspan=2 ></td></tr>
|
||||
<tr><td><b>AABox</b></td><td>AABox::contains</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td bgcolor=#C0C0C0 colspan=1 ></td></tr>
|
||||
<tr><td><b>Box</b></td><td>Box::contains</td><td>(treat as Ray)</td><td>CollisionDetection::collisionTimeForMovingPointFixedBox</td><td>(treat as Ray)</td><td>CollisionDetection::penetrationDepthForFixedBoxFixedPlane</td><td>CollisionDetection::penetrationDepthForFixedBoxFixedPlane</td><td>CollisionDetection::penetrationDepthForFixedSphereFixedBox</td><td>None (use OPCODE)</td><td>CollisionDetection::movingSpherePassesThroughFixedBox</td><td>CollisionDetection::penetrationDepthForFixedBoxFixedBox</td><td>CollisionDetection::penetrationDepthForFixedBoxFixedBox</td></tr>
|
||||
<tr><td><b>AABox</b></td><td>AABox::contains</td><td></td><td></td><td></td><td></td><td>\link CollisionDetection::fixedSolidBoxIntersectsFixedTriangle CD\endlink</td><td></td><td></td><td></td><td></td><td bgcolor=#C0C0C0 colspan=1 ></td></tr>
|
||||
<tr><td><b>Box</b></td><td>Box::contains</td><td>(treat as Ray)</td><td>\link CollisionDetection::collisionTimeForMovingPointFixedBox CD\endlink</td><td>(treat as Ray)</td><td>\link CollisionDetection::penetrationDepthForFixedBoxFixedPlane CD \endlink</td><td>\link CollisionDetection::penetrationDepthForFixedBoxFixedPlane CD\endlink</td><td>\link CollisionDetection::penetrationDepthForFixedSphereFixedBox CD\endlink</td><td>None (use OPCODE)</td><td>\link CollisionDetection::movingSpherePassesThroughFixedBox CD \endlink</td><td>\link CollisionDetection::penetrationDepthForFixedBoxFixedBox CD\endlink</td><td>\link CollisionDetection::penetrationDepthForFixedBoxFixedBox CD\endlink</td></tr>
|
||||
</table>
|
||||
|
||||
<p>
|
||||
|
|
@ -86,6 +87,8 @@ namespace G3D {
|
|||
|
||||
<i>* Note: Moving collision detection against certain primitives is equivalent to static collision
|
||||
detection against a bigger primitive. Ray, Line Segment == ``moving Point''; Capsule ==``moving Sphere''; Plane == ``moving Line''</i>
|
||||
|
||||
@deprecated Routines moving to the G3D::Intersect class in G3D 8.0
|
||||
*/
|
||||
class CollisionDetection {
|
||||
private:
|
||||
|
|
@ -404,11 +407,11 @@ public:
|
|||
Plane as well as the deepest point of the sphere that penetrates the plane
|
||||
and the plane normal at that intersection.
|
||||
|
||||
@param sphere Fixed Sphere.
|
||||
@param plane Fixed Plane.
|
||||
@param contactPoints Sphere point that penetrates the plane.
|
||||
@param sphereA Fixed Sphere.
|
||||
@param planeB Fixed Plane.
|
||||
@param contactPoints Sphere point that penetrates the plane.
|
||||
[Post Condition]
|
||||
@param contactNormals Normal at penetration point. [Post Condition]
|
||||
@param contactNormals Normal at penetration point. [Post Condition]
|
||||
|
||||
@return Depth of penetration. If there is no intersection between the
|
||||
objects then the depth will be a negative value.
|
||||
|
|
@ -477,8 +480,6 @@ public:
|
|||
@param v0 Triangle vertex 1.
|
||||
@param v1 Triangle vertex 2.
|
||||
@param v2 Triangle vertex 3
|
||||
@param location Location of collision. [Post Condition]
|
||||
(Infinite vector on no collision)
|
||||
|
||||
@return Time til collision. If there is no collision then the return
|
||||
value will be inf().
|
||||
|
|
@ -519,7 +520,7 @@ public:
|
|||
const Vector3& v2,
|
||||
Vector3& location) {
|
||||
float t = collisionTimeForMovingPointFixedTriangle(orig, dir, v0, v1, v2);
|
||||
if (t < inf()) {
|
||||
if (t < finf()) {
|
||||
location = orig + dir * t;
|
||||
}
|
||||
return t;
|
||||
|
|
@ -553,7 +554,7 @@ public:
|
|||
float t = collisionTimeForMovingPointFixedTriangle(
|
||||
orig, dir, tri.vertex(0), tri.vertex(1), tri.vertex(2));
|
||||
|
||||
if ((t < inf()) && (&location != &ignore)) {
|
||||
if ((t < finf()) && (&location != &ignore)) {
|
||||
location = orig + dir * t;
|
||||
normal = tri.normal();
|
||||
}
|
||||
|
|
@ -589,21 +590,20 @@ public:
|
|||
Vector3& location,
|
||||
Vector3& normal) {
|
||||
float t = collisionTimeForMovingPointFixedTriangle(orig, dir, v0, v1, v2);
|
||||
if (t < inf()) {
|
||||
if (t < finf()) {
|
||||
location = orig + dir * t;
|
||||
normal = (v2 - v0).cross(v1 - v0).direction();
|
||||
normal = (v1 - v0).cross(v2 - v0).direction();
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
Unlike other methods, does not support an output normal.
|
||||
If the ray origin is inside the box, returns inf() but inside
|
||||
is set to true.
|
||||
<B>Beta API</B>
|
||||
|
||||
@cite Andrew Woo, from "Graphics Gems", Academic Press, 1990
|
||||
@cite Optimized code by Pierre Terdiman, 2000 (~20-30% faster on my Celeron 500)
|
||||
@cite Optimized code by Pierre Terdiman, 2000 (~20-30% faster on Celeron 500)
|
||||
@cite Epsilon value added by Klaus Hartmann
|
||||
@cite http://www.codercorner.com/RayAABB.cpp
|
||||
*/
|
||||
|
|
@ -639,6 +639,29 @@ public:
|
|||
bool& inside = ignoreBool,
|
||||
Vector3& normal = ignore);
|
||||
|
||||
|
||||
/**
|
||||
@brief Calculates intersection of a ray and a static
|
||||
Axis-Aligned Box (AABox).
|
||||
|
||||
@note Avoids the sqrt from collisionTimeForMovingPointFixedAABox;
|
||||
early-out branches and operations optimized for Intel Core2 architecture.
|
||||
|
||||
@param invDir 1/dir
|
||||
@param location Location of collision. [Post Condition]
|
||||
@param inside Does the ray originate inside the box? [Post Condition]
|
||||
|
||||
@return True if the ray hits the box
|
||||
*/
|
||||
static bool __fastcall rayAABox(
|
||||
const Ray& ray,
|
||||
const Vector3& invDir,
|
||||
const AABox& box,
|
||||
const Vector3& boxCenter,
|
||||
float boundingRadiusSquared,
|
||||
Vector3& location,
|
||||
bool& inside);
|
||||
|
||||
/**
|
||||
Calculates time between the intersection of a moving point and a fixed
|
||||
sphere.
|
||||
|
|
@ -648,11 +671,12 @@ public:
|
|||
|
||||
@param point Moving point.
|
||||
@param velocity Point's velocity.
|
||||
@param Sphere Fixed Sphere.
|
||||
@param location Location of collision. [Post Condition]
|
||||
@param sphere Fixed Sphere.
|
||||
@param outLocation Location of collision. [Post Condition]
|
||||
@param outNormal Sphere's surface normal to collision [Post Condition]
|
||||
\param solid If true, rays inside the sphere immediately intersect (good for collision detection). If false, they hit the opposite side of the sphere (good for ray tracing).
|
||||
|
||||
@return Time til collision. If there is no collision then the return
|
||||
@return Time until collision. If there is no collision then the return
|
||||
value will be inf().
|
||||
*/
|
||||
static float collisionTimeForMovingPointFixedSphere(
|
||||
|
|
@ -660,7 +684,8 @@ public:
|
|||
const Vector3& velocity,
|
||||
const class Sphere& sphere,
|
||||
Vector3& outLocation,
|
||||
Vector3& outNormal = ignore);
|
||||
Vector3& outNormal = ignore,
|
||||
bool solid = false);
|
||||
|
||||
/**
|
||||
Calculates time between the intersection of a moving point and a fixed
|
||||
|
|
@ -721,7 +746,7 @@ public:
|
|||
@param point Moving point.
|
||||
@param velocity Point's velocity.
|
||||
@param capsule Fixed capsule.
|
||||
@param location Location of collision. [Post Condition]
|
||||
@param outLocation Location of collision. [Post Condition]
|
||||
@param outNormal Capsule's surface normal to collision [Post Condition]
|
||||
|
||||
@return Time til collision. If there is no collision then the return
|
||||
|
|
@ -741,7 +766,7 @@ public:
|
|||
@param sphere Moving sphere.
|
||||
@param velocity Sphere's velocity.
|
||||
@param plane Fixed Plane.
|
||||
@param location Location of collision -- not center position of sphere
|
||||
@param outLocation Location of collision -- not center position of sphere
|
||||
at the collision time. [Post Condition]
|
||||
@param outNormal Box's surface normal to collision [Post Condition]
|
||||
|
||||
|
|
@ -761,10 +786,11 @@ public:
|
|||
|
||||
@param sphere Moving sphere.
|
||||
@param velocity Sphere's velocity.
|
||||
@param triangle Fixed Triangle.
|
||||
@param location Location of collision -- not center position of sphere
|
||||
at the collision time. [Post Condition]
|
||||
@param outNormal Box's surface normal to collision [Post Condition]
|
||||
@param triangle Fixed Triangle. (collisions can happen on the back side of the triangle)
|
||||
@param outLocation Location of collision, if collision occurs -- not center position of sphere
|
||||
at the collision time. If there is interpenetration at the start, this point may be inside
|
||||
the sphere.
|
||||
@param b Barycentric coordinates. These are not valid unless collision occurs.
|
||||
|
||||
@return Time til collision. If there is no collision then the return
|
||||
value will be inf().
|
||||
|
|
@ -772,9 +798,9 @@ public:
|
|||
static float collisionTimeForMovingSphereFixedTriangle(
|
||||
const class Sphere& sphere,
|
||||
const Vector3& velocity,
|
||||
const Triangle& triangle,
|
||||
const Triangle& triangle,
|
||||
Vector3& outLocation,
|
||||
Vector3& outNormal = ignore);
|
||||
float b[3] = (float*)&ignore);
|
||||
|
||||
/**
|
||||
Calculates time between the intersection of a moving sphere and a fixed
|
||||
|
|
@ -786,7 +812,7 @@ public:
|
|||
@param v1 Rectangle vertex 2.
|
||||
@param v2 Rectangle vertex 3
|
||||
@param v3 Rectangle vertex 4.
|
||||
@param location Location of collision -- not center position of sphere
|
||||
@param outLocation Location of collision -- not center position of sphere
|
||||
at the collision time. [Post Condition]
|
||||
@param outNormal Box's surface normal to collision [Post Condition]
|
||||
|
||||
|
|
@ -827,29 +853,29 @@ public:
|
|||
Vector3& outLocation,
|
||||
Vector3& outNormal = ignore);
|
||||
|
||||
/**
|
||||
Calculates time between the intersection of a moving sphere and a fixed
|
||||
sphere.
|
||||
/** Calculates time between the intersection of a moving sphere
|
||||
and a fixed sphere.
|
||||
|
||||
@note This won't detect a collision if the sphere is already interpenetrating
|
||||
the fixed sphere.
|
||||
|
||||
@param movingSphere Moving sphere.
|
||||
@param velocity Sphere's velocity.
|
||||
@param fixedSphere Fixed Sphere.
|
||||
@param location Location of collision -- not center position of sphere
|
||||
at the collision time. [Post Condition]
|
||||
@param outNormal Sphere's surface normal to collision [Post Condition]
|
||||
|
||||
@return Time til collision. If there is no collision then the return
|
||||
value will be inf().
|
||||
*/
|
||||
static float collisionTimeForMovingSphereFixedSphere(
|
||||
const class Sphere& sphere,
|
||||
const Vector3& velocity,
|
||||
const class Sphere& fixedSphere,
|
||||
Vector3& outLocation,
|
||||
Vector3& outNormal = ignore);
|
||||
If they are already interpenetrating, returns 0 and @a
|
||||
location is the closest point on the surface of the fixed sphere
|
||||
to the center of the moving sphere.
|
||||
|
||||
@param sphere Moving sphere.
|
||||
@param velocity Sphere's velocity.
|
||||
@param fixedSphere Fixed Sphere.
|
||||
@param outLocation Location of collision -- not center position of sphere
|
||||
at the collision time. [Post Condition]
|
||||
@param outNormal Moving sphere's surface normal to collision [Post Condition]
|
||||
|
||||
@return Time until collision. If there is no collision then the return
|
||||
value will be inf().
|
||||
*/
|
||||
static float collisionTimeForMovingSphereFixedSphere(
|
||||
const Sphere& sphere,
|
||||
const Vector3& velocity,
|
||||
const Sphere& fixedSphere,
|
||||
Vector3& outLocation,
|
||||
Vector3& outNormal = ignore);
|
||||
|
||||
/**
|
||||
Calculates time between the intersection of a moving sphere and a fixed
|
||||
|
|
@ -940,8 +966,8 @@ public:
|
|||
and direction can be used in this function if already pre-calculated. This
|
||||
prevents doing the same work twice.
|
||||
|
||||
@param v0 line vertex 1.
|
||||
@param v1 line vertex 2.
|
||||
@param v0 line vertex 0.
|
||||
@param v1 line vertex 1.
|
||||
@param edgeDirection The direction of the segment (unit length).
|
||||
@param edgeLength The length of the segment.
|
||||
@param point External point.
|
||||
|
|
@ -952,22 +978,22 @@ public:
|
|||
const Vector3& v0,
|
||||
const Vector3& v1,
|
||||
const Vector3& edgeDirection,
|
||||
float edgeLength,
|
||||
float edgeLength,
|
||||
const Vector3& point);
|
||||
|
||||
/**
|
||||
Finds the closest point on the perimeter of the triangle to an external point;
|
||||
given a triangle defined by three points v0, v1, & v2, and the external point.
|
||||
|
||||
@param v0 Triangle vertex 1.
|
||||
@param v1 Triangle vertex 2.
|
||||
@param v2 Triangle vertex 3.
|
||||
@param v0 Triangle vertex 0.
|
||||
@param v1 Triangle vertex 1.
|
||||
@param v2 Triangle vertex 2.
|
||||
@param point External point.
|
||||
|
||||
@return Closests point to <code>point</code> on the perimeter of the
|
||||
triangle.
|
||||
*/
|
||||
static Vector3 closestPointToTrianglePerimeter(
|
||||
static Vector3 closestPointOnTrianglePerimeter(
|
||||
const Vector3& v0,
|
||||
const Vector3& v1,
|
||||
const Vector3& v2,
|
||||
|
|
@ -982,42 +1008,56 @@ public:
|
|||
and direction can be used in this function if already pre-calculated. This
|
||||
prevents doing the same work twice.
|
||||
|
||||
@param v0 Triangle vertex 1.
|
||||
@param v1 Triangle vertex 2.
|
||||
@param v2 Triangle vertex 3.
|
||||
@param point External point.
|
||||
@param v Triangle vertices.
|
||||
@param point External point.
|
||||
@param edgeIndex The point lies on the edge between v[edgeIndex] and v[(edgeIndex + 1) % 3]
|
||||
|
||||
@return Closests point to <code>point</code> on the perimeter of the
|
||||
@return Closest point to <code>point</code> on the perimeter of the
|
||||
triangle.
|
||||
*/
|
||||
static Vector3 closestPointToTrianglePerimeter(
|
||||
static Vector3 closestPointOnTrianglePerimeter(
|
||||
const Vector3 v[3],
|
||||
const Vector3 edgeDirection[3],
|
||||
const double edgeLength[3],
|
||||
const Vector3& point);
|
||||
const float edgeLength[3],
|
||||
const Vector3& point,
|
||||
int& edgeIndex);
|
||||
|
||||
/**
|
||||
Tests whether a point is contained within the triangle defined by
|
||||
v0, v1, & v2 and its plane's normal.
|
||||
v0, v1, and v2 and its plane's normal.
|
||||
|
||||
@param v0 Triangle vertex 1.
|
||||
@param v1 Triangle vertex 2.
|
||||
@param v2 Triangle vertex 3.
|
||||
@param v0 Triangle vertex 0.
|
||||
@param v1 Triangle vertex 1.
|
||||
@param v2 Triangle vertex 2.
|
||||
@param normal Normal to triangle's plane.
|
||||
@param point The point in question.
|
||||
@param primaryAxis Primary axis of triangle. This will be detected
|
||||
if not given. This parameter is provided as an optimization.
|
||||
@param b Barycentric coordinates; b[i] is the weight on v[i]
|
||||
|
||||
@return true - if point is inside the triangle.
|
||||
@return false - otherwise
|
||||
*/
|
||||
static bool isPointInsideTriangle(
|
||||
const Vector3& v0,
|
||||
const Vector3& v1,
|
||||
const Vector3& v2,
|
||||
const Vector3& normal,
|
||||
const Vector3& point,
|
||||
float b[3],
|
||||
Vector3::Axis primaryAxis = Vector3::DETECT_AXIS);
|
||||
|
||||
inline static bool isPointInsideTriangle(
|
||||
const Vector3& v0,
|
||||
const Vector3& v1,
|
||||
const Vector3& v2,
|
||||
const Vector3& normal,
|
||||
const Vector3& point,
|
||||
Vector3::Axis primaryAxis = Vector3::DETECT_AXIS);
|
||||
Vector3::Axis primaryAxis = Vector3::DETECT_AXIS) {
|
||||
|
||||
float b[3];
|
||||
return isPointInsideTriangle(v0, v1, v2, normal, point, b, primaryAxis);
|
||||
}
|
||||
|
||||
/**
|
||||
Tests for the intersection of a moving sphere and a fixed box in a
|
||||
|
|
@ -1088,6 +1128,14 @@ public:
|
|||
const Sphere& sphere,
|
||||
const Box& box);
|
||||
|
||||
static bool fixedSolidSphereIntersectsFixedTriangle(
|
||||
const Sphere& sphere,
|
||||
const Triangle& triangle);
|
||||
|
||||
static bool fixedSolidBoxIntersectsFixedTriangle(
|
||||
const AABox& box,
|
||||
const Triangle& triangle);
|
||||
|
||||
/**
|
||||
Tests whether a point is inside a rectangle defined by the vertexes
|
||||
v0, v1, v2, & v3, and the rectangle's plane normal.
|
||||
|
|
|
|||
144
dep/include/g3dlite/G3D/Color1.h
Normal file
144
dep/include/g3dlite/G3D/Color1.h
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
/**
|
||||
@file Color1.h
|
||||
|
||||
Monochrome Color class
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
@created 2007-01-31
|
||||
@edited 2009-03-20
|
||||
|
||||
Copyright 2000-2009, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_COLOR1_H
|
||||
#define G3D_COLOR1_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/HashTrait.h"
|
||||
#include <string>
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
Monochrome color. This is just a float, but it has nice semantics
|
||||
because a scaling by 255 automatically occurs when switching between
|
||||
fixed point (Color1uint8) and floating point (Color1) formats.
|
||||
*/
|
||||
class Color1 {
|
||||
private:
|
||||
// Hidden operators
|
||||
bool operator<(const Color1&) const;
|
||||
bool operator>(const Color1&) const;
|
||||
bool operator<=(const Color1&) const;
|
||||
bool operator>=(const Color1&) const;
|
||||
|
||||
public:
|
||||
float value;
|
||||
|
||||
/**
|
||||
Initializes to 0
|
||||
*/
|
||||
inline Color1() : value(0) {}
|
||||
|
||||
Color1(class BinaryInput& bi);
|
||||
|
||||
inline explicit Color1(float v) : value(v) {
|
||||
}
|
||||
|
||||
inline bool isZero() const {
|
||||
return value == 0.0f;
|
||||
}
|
||||
|
||||
inline bool isOne() const {
|
||||
return value == 1.0f;
|
||||
}
|
||||
|
||||
static const Color1& one();
|
||||
|
||||
static const Color1& zero();
|
||||
|
||||
/** Returns the value three times */
|
||||
class Color3 rgb() const;
|
||||
|
||||
Color1 (const class Color1uint8& other);
|
||||
|
||||
void serialize(class BinaryOutput& bo) const;
|
||||
void deserialize(class BinaryInput& bi);
|
||||
|
||||
Color1 operator+ (const Color1& other) const {
|
||||
return Color1(value + other.value);
|
||||
}
|
||||
|
||||
Color1 operator+ (const float other) const {
|
||||
return Color1(value + other);
|
||||
}
|
||||
|
||||
Color1& operator+= (const Color1 other) {
|
||||
value += other.value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Color1& operator-= (const Color1 other) {
|
||||
value -= other.value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Color1 operator- (const Color1& other) const {
|
||||
return Color1(value - other.value);
|
||||
}
|
||||
|
||||
Color1 operator- (const float other) const {
|
||||
return Color1(value - other);
|
||||
}
|
||||
|
||||
Color1 operator- () const {
|
||||
return Color1(-value);
|
||||
}
|
||||
|
||||
Color1 operator* (const Color1& other) const {
|
||||
return Color1(value * other.value);
|
||||
}
|
||||
|
||||
Color1 operator* (const float other) const {
|
||||
return Color1(value * other);
|
||||
}
|
||||
|
||||
Color1 operator/ (const Color1& other) const {
|
||||
return Color1(value / other.value);
|
||||
}
|
||||
|
||||
Color1 operator/ (const float other) const {
|
||||
return Color1(value / other);
|
||||
}
|
||||
|
||||
inline Color1 max(const Color1& other) const {
|
||||
return Color1(G3D::max(value, other.value));
|
||||
}
|
||||
|
||||
inline Color1 min(const Color1& other) const {
|
||||
return Color1(G3D::min(value, other.value));
|
||||
}
|
||||
|
||||
inline Color1 lerp(const Color1& other, float a) const {
|
||||
return Color1(value + (other.value - value) * a);
|
||||
|
||||
}
|
||||
|
||||
inline size_t hashCode() const {
|
||||
return (size_t)(value * 0xFFFFFF);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template <>
|
||||
struct HashTrait<G3D::Color1> {
|
||||
static size_t hashCode(const G3D::Color1& key) {
|
||||
return key.hashCode();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
91
dep/include/g3dlite/G3D/Color1uint8.h
Normal file
91
dep/include/g3dlite/G3D/Color1uint8.h
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
/**
|
||||
@file Color1uint8.h
|
||||
|
||||
@maintainer Morgan McGuire, graphics3d.com
|
||||
|
||||
@created 2007-01-30
|
||||
@edited 2007-01-30
|
||||
|
||||
Copyright 2000-2007, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_COLOR1UINT8_H
|
||||
#define G3D_COLOR1UINT8_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
Represents a Color1 as a packed integer. Convenient
|
||||
for creating unsigned int vertex arrays.
|
||||
|
||||
<B>WARNING</B>: Integer color formats are different than
|
||||
integer vertex formats. The color channels are automatically
|
||||
scaled by 255 (because OpenGL automatically scales integer
|
||||
colors back by this factor). So Color3(1,1,1) == Color3uint8(255,255,255)
|
||||
but Vector3(1,1,1) == Vector3int16(1,1,1).
|
||||
|
||||
<B>Note</B>:
|
||||
Conversion of a float32 to uint8 is accomplished by min(iFloor(f * 256)) and
|
||||
back to float32 by u / 255.0f. This gives equal size intervals.
|
||||
Consider a number line from 0 to 1 and a corresponding one from 0 to 255. If we use iRound(x * 255), then the mapping for three critical intervals are:
|
||||
|
||||
<pre>
|
||||
let s = 0.5/255
|
||||
float int size
|
||||
[0, s) -> 0 s
|
||||
[s, s * 3) -> 1 2*s
|
||||
(1 - s, 1] -> 255 s
|
||||
</pre>
|
||||
|
||||
If we use max(floor(x * 256), 255), then we get:
|
||||
|
||||
<pre>
|
||||
let s = 1/256
|
||||
float int size
|
||||
[0, s) -> 0 s
|
||||
[s, 2 * s) -> 1 s
|
||||
(1 - s, 1] -> 255 s
|
||||
</PRE>
|
||||
and the intervals are all the same size, thus giving equal precision to all values.
|
||||
*/
|
||||
G3D_BEGIN_PACKED_CLASS(1)
|
||||
class Color1uint8 {
|
||||
private:
|
||||
// Hidden operators
|
||||
bool operator<(const Color1uint8&) const;
|
||||
bool operator>(const Color1uint8&) const;
|
||||
bool operator<=(const Color1uint8&) const;
|
||||
bool operator>=(const Color1uint8&) const;
|
||||
|
||||
public:
|
||||
|
||||
uint8 value;
|
||||
|
||||
Color1uint8() : value(0) {}
|
||||
|
||||
explicit Color1uint8(const uint8 _v) : value(_v) {}
|
||||
|
||||
Color1uint8(const class Color1& c);
|
||||
|
||||
Color1uint8(class BinaryInput& bi);
|
||||
|
||||
void serialize(class BinaryOutput& bo) const;
|
||||
|
||||
void deserialize(class BinaryInput& bi);
|
||||
|
||||
inline bool operator==(const Color1uint8& other) const {
|
||||
return value == other.value;
|
||||
}
|
||||
|
||||
inline bool operator!=(const Color1uint8& other) const {
|
||||
return value != other.value;
|
||||
}
|
||||
|
||||
}
|
||||
G3D_END_PACKED_CLASS(1)
|
||||
}
|
||||
#endif
|
||||
432
dep/include/g3dlite/G3D/Color3.h
Normal file
432
dep/include/g3dlite/G3D/Color3.h
Normal file
|
|
@ -0,0 +1,432 @@
|
|||
/**
|
||||
@file Color3.h
|
||||
|
||||
Color class
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
@cite Portions based on Dave Eberly's Magic Software Library
|
||||
at <A HREF="http://www.magic-software.com">http://www.magic-software.com</A>
|
||||
|
||||
@created 2001-06-02
|
||||
@edited 2009-04-28
|
||||
|
||||
Copyright 2000-2009, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_Color3_h
|
||||
#define G3D_Color3_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/HashTrait.h"
|
||||
#include "G3D/Color1.h"
|
||||
#include <string>
|
||||
|
||||
namespace G3D {
|
||||
class Any;
|
||||
|
||||
/**
|
||||
Do not subclass-- this implementation makes assumptions about the
|
||||
memory layout.
|
||||
*/
|
||||
class Color3 {
|
||||
private:
|
||||
// Hidden operators
|
||||
bool operator<(const Color3&) const;
|
||||
bool operator>(const Color3&) const;
|
||||
bool operator<=(const Color3&) const;
|
||||
bool operator>=(const Color3&) const;
|
||||
|
||||
public:
|
||||
/**
|
||||
Does not initialize fields.
|
||||
*/
|
||||
Color3();
|
||||
|
||||
/** \param any Must be in one of the following forms:
|
||||
- Color3(#, #, #)
|
||||
- Color3::fromARGB(#)
|
||||
- Color3{r = #, g = #, b = #)
|
||||
- Color3::one()
|
||||
- Color3::zero()
|
||||
*/
|
||||
Color3(const Any& any);
|
||||
|
||||
/** Converts the Color3 to an Any. */
|
||||
operator Any() const;
|
||||
|
||||
explicit Color3(class BinaryInput& bi);
|
||||
|
||||
Color3(float r, float g, float b);
|
||||
Color3(float v) : r(v), g(v), b(v) {}
|
||||
|
||||
explicit Color3(const class Vector3& v);
|
||||
|
||||
explicit Color3(const float value[3]);
|
||||
|
||||
/** Returns this color */
|
||||
const Color3& rgb() const {
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
Initialize from another color.
|
||||
*/
|
||||
Color3 (const Color3& other);
|
||||
|
||||
Color3 (const class Color3uint8& other);
|
||||
|
||||
inline bool isZero() const {
|
||||
return (r == 0.0f) && (g == 0.0f) && (b == 0.0f);
|
||||
}
|
||||
|
||||
inline bool isOne() const {
|
||||
return (r == 1.0f) && (g == 1.0f) && (b == 1.0f);
|
||||
}
|
||||
|
||||
bool isFinite() const;
|
||||
|
||||
/**
|
||||
Initialize from an HTML-style color (e.g. 0xFF0000 == RED)
|
||||
*/
|
||||
static Color3 fromARGB(uint32);
|
||||
|
||||
/** Returns one of the color wheel colors (e.g. RED, GREEN, CYAN).
|
||||
Does not include white, black, or gray. */
|
||||
static const Color3& wheelRandom();
|
||||
|
||||
/** Generate colors according to the ANSI color set, mod 16.
|
||||
\sa pastelMap */
|
||||
static Color3 ansiMap(uint32 i);
|
||||
|
||||
/**
|
||||
Generate colors using a hash such that adjacent values
|
||||
are unlikely to have similar colors.
|
||||
|
||||
Useful for rendering with
|
||||
stable but arbitrary colors, e.g., when debugging a mesh
|
||||
algorithm.
|
||||
|
||||
\sa ansiMap
|
||||
*/
|
||||
static Color3 pastelMap(uint32 i);
|
||||
|
||||
/**
|
||||
* Channel value.
|
||||
*/
|
||||
float r, g, b;
|
||||
|
||||
void serialize(class BinaryOutput& bo) const;
|
||||
void deserialize(class BinaryInput& bi);
|
||||
|
||||
// access vector V as V[0] = V.r, V[1] = V.g, V[2] = V.b
|
||||
//
|
||||
// WARNING. These member functions rely on
|
||||
// (1) Color3 not having virtual functions
|
||||
// (2) the data packed in a 3*sizeof(float) memory block
|
||||
const float& operator[] (int i) const;
|
||||
float& operator[] (int i);
|
||||
|
||||
// assignment and comparison
|
||||
Color3& operator= (const Color3& rkVector);
|
||||
bool operator== (const Color3& rkVector) const;
|
||||
bool operator!= (const Color3& rkVector) const;
|
||||
size_t hashCode() const;
|
||||
|
||||
// arithmetic operations
|
||||
Color3 operator+ (const Color3& rkVector) const;
|
||||
Color3 operator- (const Color3& rkVector) const;
|
||||
inline Color3 operator* (float s) const {
|
||||
return Color3(r * s, g * s, b * s);
|
||||
}
|
||||
Color3 operator* (const Color3& rkVector) const;
|
||||
inline Color3 operator/ (float fScalar) const {
|
||||
return (*this) * (1.0f / fScalar);
|
||||
}
|
||||
Color3 operator- () const;
|
||||
|
||||
// arithmetic updates
|
||||
Color3& operator+= (const Color3& rkVector);
|
||||
Color3& operator-= (const Color3& rkVector);
|
||||
Color3& operator*= (const Color3& rkVector);
|
||||
Color3& operator*= (float fScalar);
|
||||
Color3& operator/= (float fScalar);
|
||||
|
||||
bool fuzzyEq(const Color3& other) const;
|
||||
bool fuzzyNe(const Color3& other) const;
|
||||
|
||||
// vector operations
|
||||
float length () const;
|
||||
Color3 direction() const;
|
||||
float squaredLength () const;
|
||||
float dot (const Color3& rkVector) const;
|
||||
float unitize (float fTolerance = 1e-06);
|
||||
Color3 cross (const Color3& rkVector) const;
|
||||
Color3 unitCross (const Color3& rkVector) const;
|
||||
|
||||
inline Color3 pow(const Color3& other) const {
|
||||
return Color3(::pow(r, other.r), ::pow(g, other.g), ::pow(b, other.b));
|
||||
}
|
||||
|
||||
inline Color3 pow(float other) const {
|
||||
return Color3(::pow(r, other), ::pow(g, other), ::pow(b, other));
|
||||
}
|
||||
|
||||
inline Color3 max(const Color3& other) const {
|
||||
return Color3(G3D::max(r, other.r), G3D::max(g, other.g), G3D::max(b, other.b));
|
||||
}
|
||||
|
||||
inline Color3 min(const Color3& other) const {
|
||||
return Color3(G3D::min(r, other.r), G3D::min(g, other.g), G3D::min(b, other.b));
|
||||
}
|
||||
|
||||
/** Smallest element */
|
||||
inline float min() const {
|
||||
return G3D::min(G3D::min(r, g), b);
|
||||
}
|
||||
|
||||
/** Largest element */
|
||||
inline float max() const {
|
||||
return G3D::max(G3D::max(r, g), b);
|
||||
}
|
||||
|
||||
inline Color3 lerp(const Color3& other, float a) const {
|
||||
return (*this) + (other - *this) * a;
|
||||
|
||||
}
|
||||
|
||||
inline float sum() const {
|
||||
return r + g + b;
|
||||
}
|
||||
|
||||
inline float average() const {
|
||||
return sum() / 3.0f;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Converts from HSV to RGB , note: toHSV(fromHSV(_hsv)) may not be _hsv, if it is at a grey point or black point.
|
||||
* The components of _hsv should lie in the unit interval.
|
||||
* @cite Alvy Ray Smith SIGGRAPH 1978 "Color Gamut Transform Pairs"
|
||||
**/
|
||||
static Color3 fromHSV(const Vector3& _hsv);
|
||||
static Vector3 toHSV(const Color3& _rgb);
|
||||
|
||||
/** Duplicates the matlab jet colormap maps [0,1] --> (r,g,b) where blue is close to 0 and red is close to 1. */
|
||||
static Color3 jetColorMap(const float& val);
|
||||
|
||||
/** Returns colors with maximum saturation and value @param hue [0, 1]*/
|
||||
static Color3 rainbowColorMap(float hue);
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
/** Random unit vector */
|
||||
static Color3 random();
|
||||
|
||||
// Special values.
|
||||
// Intentionally not inlined: see Matrix3::identity() for details.
|
||||
static const Color3& red();
|
||||
static const Color3& green();
|
||||
static const Color3& blue();
|
||||
static const Color3& purple();
|
||||
static const Color3& cyan();
|
||||
static const Color3& yellow();
|
||||
static const Color3& brown();
|
||||
static const Color3& orange();
|
||||
static const Color3& black();
|
||||
static const Color3& gray();
|
||||
static const Color3& white();
|
||||
|
||||
static const Color3& zero();
|
||||
static const Color3& one();
|
||||
|
||||
inline Color3 bgr() const {
|
||||
return Color3(b, g, r);
|
||||
}
|
||||
};
|
||||
|
||||
inline G3D::Color3 operator* (float s, const G3D::Color3& c) {
|
||||
return c * s;
|
||||
}
|
||||
|
||||
inline G3D::Color3 operator* (G3D::Color1& s, const G3D::Color3& c) {
|
||||
return c * s.value;
|
||||
}
|
||||
|
||||
inline G3D::Color3 operator* (const G3D::Color3& c, G3D::Color1& s) {
|
||||
return c * s.value;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Color3::Color3 () {
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline Color3::Color3(float fX, float fY, float fZ) {
|
||||
r = fX;
|
||||
g = fY;
|
||||
b = fZ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Color3::Color3(const float afCoordinate[3]) {
|
||||
r = afCoordinate[0];
|
||||
g = afCoordinate[1];
|
||||
b = afCoordinate[2];
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Color3::Color3 (const Color3& rkVector) {
|
||||
r = rkVector.r;
|
||||
g = rkVector.g;
|
||||
b = rkVector.b;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline float& Color3::operator[] (int i) {
|
||||
return ((float*)this)[i];
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline const float& Color3::operator[] (int i) const {
|
||||
return ((float*)this)[i];
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline bool Color3::fuzzyEq(const Color3& other) const {
|
||||
return G3D::fuzzyEq((*this - other).squaredLength(), 0);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline bool Color3::fuzzyNe(const Color3& other) const {
|
||||
return G3D::fuzzyNe((*this - other).squaredLength(), 0);
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Color3& Color3::operator= (const Color3& rkVector) {
|
||||
r = rkVector.r;
|
||||
g = rkVector.g;
|
||||
b = rkVector.b;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline bool Color3::operator== (const Color3& rkVector) const {
|
||||
return ( r == rkVector.r && g == rkVector.g && b == rkVector.b );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline bool Color3::operator!= (const Color3& rkVector) const {
|
||||
return ( r != rkVector.r || g != rkVector.g || b != rkVector.b );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Color3 Color3::operator+ (const Color3& rkVector) const {
|
||||
return Color3(r + rkVector.r, g + rkVector.g, b + rkVector.b);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Color3 Color3::operator- (const Color3& rkVector) const {
|
||||
return Color3(r -rkVector.r, g - rkVector.g, b - rkVector.b);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Color3 Color3::operator* (const Color3& rkVector) const {
|
||||
return Color3(r * rkVector.r, g * rkVector.g, b * rkVector.b);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Color3 Color3::operator- () const {
|
||||
return Color3( -r, -g, -b);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Color3& Color3::operator+= (const Color3& rkVector) {
|
||||
r += rkVector.r;
|
||||
g += rkVector.g;
|
||||
b += rkVector.b;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Color3& Color3::operator-= (const Color3& rkVector) {
|
||||
r -= rkVector.r;
|
||||
g -= rkVector.g;
|
||||
b -= rkVector.b;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Color3& Color3::operator*= (float fScalar) {
|
||||
r *= fScalar;
|
||||
g *= fScalar;
|
||||
b *= fScalar;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Color3& Color3::operator*= (const Color3& rkVector) {
|
||||
r *= rkVector.r;
|
||||
g *= rkVector.g;
|
||||
b *= rkVector.b;
|
||||
return *this;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
inline float Color3::squaredLength () const {
|
||||
return r*r + g*g + b*b;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline float Color3::length () const {
|
||||
return sqrtf(r*r + g*g + b*b);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Color3 Color3::direction () const {
|
||||
float lenSquared = r * r + g * g + b * b;
|
||||
|
||||
if (lenSquared != 1.0f) {
|
||||
return *this / sqrtf(lenSquared);
|
||||
} else {
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline float Color3::dot (const Color3& rkVector) const {
|
||||
return r*rkVector.r + g*rkVector.g + b*rkVector.b;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Color3 Color3::cross (const Color3& rkVector) const {
|
||||
return Color3(g*rkVector.b - b*rkVector.g, b*rkVector.r - r*rkVector.b,
|
||||
r*rkVector.g - g*rkVector.r);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Color3 Color3::unitCross (const Color3& rkVector) const {
|
||||
Color3 kCross(g*rkVector.b - b*rkVector.g, b*rkVector.r - r*rkVector.b,
|
||||
r*rkVector.g - g*rkVector.r);
|
||||
kCross.unitize();
|
||||
return kCross;
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
template <> struct HashTrait<G3D::Color3> {
|
||||
static size_t hashCode(const G3D::Color3& key) {
|
||||
return key.hashCode();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
110
dep/include/g3dlite/G3D/Color3uint8.h
Normal file
110
dep/include/g3dlite/G3D/Color3uint8.h
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
/**
|
||||
@file Color3uint8.h
|
||||
|
||||
@maintainer Morgan McGuire, graphics3d.com
|
||||
|
||||
@created 2003-04-07
|
||||
@edited 2006-06-24
|
||||
|
||||
Copyright 2000-2006, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_COLOR3UINT8_H
|
||||
#define G3D_COLOR3UINT8_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
Represents a Color3 as a packed integer. Convenient
|
||||
for creating unsigned int vertex arrays. Used by
|
||||
G3D::GImage as the underlying format.
|
||||
|
||||
<B>WARNING</B>: Integer color formats are different than
|
||||
integer vertex formats. The color channels are automatically
|
||||
scaled by 255 (because OpenGL automatically scales integer
|
||||
colors back by this factor). So Color3(1,1,1) == Color3uint8(255,255,255)
|
||||
but Vector3(1,1,1) == Vector3int16(1,1,1).
|
||||
*/
|
||||
|
||||
G3D_BEGIN_PACKED_CLASS(1)
|
||||
|
||||
class Color3uint8 {
|
||||
private:
|
||||
// Hidden operators
|
||||
bool operator<(const Color3uint8&) const;
|
||||
bool operator>(const Color3uint8&) const;
|
||||
bool operator<=(const Color3uint8&) const;
|
||||
bool operator>=(const Color3uint8&) const;
|
||||
|
||||
public:
|
||||
uint8 r;
|
||||
uint8 g;
|
||||
uint8 b;
|
||||
|
||||
Color3uint8() : r(0), g(0), b(0) {}
|
||||
|
||||
Color3uint8(const uint8 _r, const uint8 _g, const uint8 _b) : r(_r), g(_g), b(_b) {}
|
||||
|
||||
Color3uint8(const class Color3& c);
|
||||
|
||||
Color3uint8(class BinaryInput& bi);
|
||||
|
||||
inline static Color3uint8 fromARGB(uint32 i) {
|
||||
Color3uint8 c;
|
||||
c.r = (i >> 16) & 0xFF;
|
||||
c.g = (i >> 8) & 0xFF;
|
||||
c.b = i & 0xFF;
|
||||
return c;
|
||||
}
|
||||
|
||||
inline Color3uint8 bgr() const {
|
||||
return Color3uint8(b, g, r);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the color packed into a uint32
|
||||
(the upper byte is 0xFF)
|
||||
*/
|
||||
inline uint32 asUInt32() const {
|
||||
return (0xFF << 24) + ((uint32)r << 16) + ((uint32)g << 8) + b;
|
||||
}
|
||||
|
||||
void serialize(class BinaryOutput& bo) const;
|
||||
|
||||
void deserialize(class BinaryInput& bi);
|
||||
|
||||
// access vector V as V[0] = V.r, V[1] = V.g, V[2] = V.b
|
||||
//
|
||||
// WARNING. These member functions rely on
|
||||
// (1) Color3 not having virtual functions
|
||||
// (2) the data packed in a 3*sizeof(uint8) memory block
|
||||
uint8& operator[] (int i) const {
|
||||
debugAssert((unsigned int)i < 3);
|
||||
return ((uint8*)this)[i];
|
||||
}
|
||||
|
||||
operator uint8* () {
|
||||
return (G3D::uint8*)this;
|
||||
}
|
||||
|
||||
operator const uint8* () const {
|
||||
return (uint8*)this;
|
||||
}
|
||||
|
||||
bool operator==(const Color3uint8& other) const {
|
||||
return (other.r == r) && (other.g == g) && (other.b == b);
|
||||
}
|
||||
|
||||
bool operator!=(const Color3uint8& other) const {
|
||||
return (other.r != r) && (other.g != g) && (other.b != b);
|
||||
}
|
||||
}
|
||||
G3D_END_PACKED_CLASS(1)
|
||||
|
||||
} // namespace G3D
|
||||
|
||||
#endif
|
||||
338
dep/include/g3dlite/G3D/Color4.h
Normal file
338
dep/include/g3dlite/G3D/Color4.h
Normal file
|
|
@ -0,0 +1,338 @@
|
|||
/**
|
||||
@file Color4.h
|
||||
|
||||
Color class
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
@cite Portions based on Dave Eberly's Magic Software Library
|
||||
at <A HREF="http://www.magic-software.com">http://www.magic-software.com</A>
|
||||
|
||||
@created 2002-06-25
|
||||
@edited 2009-11-15
|
||||
|
||||
Copyright 2000-2009, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_Color4_h
|
||||
#define G3D_Color4_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/Color3.h"
|
||||
#include <string>
|
||||
|
||||
namespace G3D {
|
||||
|
||||
class Any;
|
||||
|
||||
/**
|
||||
Do not subclass-- this implementation makes assumptions about the
|
||||
memory layout.
|
||||
*/
|
||||
class Color4 {
|
||||
private:
|
||||
// Hidden operators
|
||||
bool operator<(const Color4&) const;
|
||||
bool operator>(const Color4&) const;
|
||||
bool operator<=(const Color4&) const;
|
||||
bool operator>=(const Color4&) const;
|
||||
|
||||
public:
|
||||
|
||||
/** \param any Must be in one of the following forms:
|
||||
- Color4(#, #, #, #)
|
||||
- Color4::fromARGB(#)
|
||||
- Color4{r = #, g = #, b = #, a = #)
|
||||
*/
|
||||
Color4(const Any& any);
|
||||
|
||||
/** Converts the Color4 to an Any. */
|
||||
operator Any() const;
|
||||
|
||||
/**
|
||||
* Does not initialize fields.
|
||||
*/
|
||||
Color4 ();
|
||||
|
||||
Color4(const Color3& c3, float a = 1.0);
|
||||
|
||||
Color4(const class Color4uint8& c);
|
||||
|
||||
Color4(class BinaryInput& bi);
|
||||
|
||||
Color4(const class Vector4& v);
|
||||
|
||||
Color4(float r, float g, float b, float a = 1.0);
|
||||
|
||||
static const Color4& one();
|
||||
|
||||
Color4(float value[4]);
|
||||
|
||||
/**
|
||||
* Initialize from another color.
|
||||
*/
|
||||
Color4(const Color4& other);
|
||||
|
||||
|
||||
inline bool isZero() const {
|
||||
return (r == 0.0f) && (g == 0.0f) && (b == 0.0f) && (a == 0.0f);
|
||||
}
|
||||
|
||||
inline bool isOne() const {
|
||||
return (r == 1.0f) && (g == 1.0f) && (b == 1.0f) && (a == 1.0f);
|
||||
}
|
||||
|
||||
void serialize(class BinaryOutput& bo) const;
|
||||
void deserialize(class BinaryInput& bi);
|
||||
|
||||
/**
|
||||
Initialize from an HTML-style color (e.g. 0xFFFF0000 == RED)
|
||||
*/
|
||||
static Color4 fromARGB(uint32);
|
||||
|
||||
/**
|
||||
* Channel values.
|
||||
*/
|
||||
float r, g, b, a;
|
||||
|
||||
inline Color3 rgb() const {
|
||||
return Color3(r, g, b);
|
||||
}
|
||||
|
||||
// access vector V as V[0] = V.r, V[1] = V.g, V[2] = V.b, v[3] = V.a
|
||||
//
|
||||
// WARNING. These member functions rely on
|
||||
// (1) Color4 not having virtual functions
|
||||
// (2) the data packed in a 3*sizeof(float) memory block
|
||||
float& operator[] (int i) const;
|
||||
|
||||
// assignment and comparison
|
||||
Color4& operator= (const Color4& rkVector);
|
||||
bool operator== (const Color4& rkVector) const;
|
||||
bool operator!= (const Color4& rkVector) const;
|
||||
size_t hashCode() const;
|
||||
|
||||
// arithmetic operations
|
||||
Color4 operator+ (const Color4& rkVector) const;
|
||||
Color4 operator- (const Color4& rkVector) const;
|
||||
Color4 operator* (float fScalar) const;
|
||||
inline Color4 operator* (const Color4& k) const {
|
||||
return Color4(r*k.r, g*k.g, b*k.b, a * k.a);
|
||||
}
|
||||
Color4 operator/ (float fScalar) const;
|
||||
Color4 operator- () const;
|
||||
friend Color4 operator* (double fScalar, const Color4& rkVector);
|
||||
|
||||
// arithmetic updates
|
||||
Color4& operator+= (const Color4& rkVector);
|
||||
Color4& operator-= (const Color4& rkVector);
|
||||
Color4& operator*= (float fScalar);
|
||||
Color4& operator/= (float fScalar);
|
||||
|
||||
bool fuzzyEq(const Color4& other) const;
|
||||
bool fuzzyNe(const Color4& other) const;
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
inline Color4 max(const Color4& other) const {
|
||||
return Color4(G3D::max(r, other.r), G3D::max(g, other.g), G3D::max(b, other.b), G3D::max(a, other.a));
|
||||
}
|
||||
|
||||
inline Color4 min(const Color4& other) const {
|
||||
return Color4(G3D::min(r, other.r), G3D::min(g, other.g), G3D::min(b, other.b), G3D::min(a, other.a));
|
||||
}
|
||||
|
||||
/** r + g + b + a */
|
||||
inline float sum() const {
|
||||
return r + g + b + a;
|
||||
}
|
||||
|
||||
inline Color4 lerp(const Color4& other, float a) const {
|
||||
return (*this) + (other - *this) * a;
|
||||
|
||||
}
|
||||
|
||||
// Special values.
|
||||
// Intentionally not inlined: see Matrix3::identity() for details.
|
||||
static const Color4& zero();
|
||||
static const Color4& clear();
|
||||
|
||||
static const Color4& inf();
|
||||
static const Color4& nan();
|
||||
|
||||
inline bool isFinite() const {
|
||||
return G3D::isFinite(r) && G3D::isFinite(g) && G3D::isFinite(b) && G3D::isFinite(a);
|
||||
}
|
||||
|
||||
inline Color3 bgr() const {
|
||||
return Color3(b, g, r);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
Extends the c3 with alpha = 1.0
|
||||
*/
|
||||
Color4 operator*(const Color3& c3, const Color4& c4);
|
||||
|
||||
|
||||
inline Color4 operator*(const Color3& c3, const Color4& c4) {
|
||||
return Color4(c3.r * c4.r, c3.g * c4.g, c3.b * c4.b, c4.a);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline Color4::Color4 () {
|
||||
// For efficiency in construction of large arrays of vectors, the
|
||||
// default constructor does not initialize the vector.
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline Color4::Color4(const Color3& c3, float a) {
|
||||
r = c3.r;
|
||||
g = c3.g;
|
||||
b = c3.b;
|
||||
this->a = a;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline Color4::Color4(
|
||||
float r,
|
||||
float g,
|
||||
float b,
|
||||
float a) :
|
||||
r(r), g(g), b(b), a(a) {
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Color4::Color4 (float afCoordinate[4]) {
|
||||
r = afCoordinate[0];
|
||||
g = afCoordinate[1];
|
||||
b = afCoordinate[2];
|
||||
a = afCoordinate[3];
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline Color4::Color4(
|
||||
const Color4& other) {
|
||||
|
||||
r = other.r;
|
||||
g = other.g;
|
||||
b = other.b;
|
||||
a = other.a;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline float& Color4::operator[] (int i) const {
|
||||
return ((float*)this)[i];
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline bool Color4::fuzzyEq(const Color4& other) const {
|
||||
Color4 dif = (*this - other);
|
||||
return G3D::fuzzyEq(dif.r * dif.r + dif.g * dif.g + dif.b * dif.b + dif.a * dif.a, 0);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline bool Color4::fuzzyNe(const Color4& other) const {
|
||||
Color4 dif = (*this - other);
|
||||
return G3D::fuzzyNe(dif.r * dif.r + dif.g * dif.g + dif.b * dif.b + dif.a * dif.a, 0);
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Color4& Color4::operator= (const Color4& other) {
|
||||
r = other.r;
|
||||
g = other.g;
|
||||
b = other.b;
|
||||
a = other.a;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline bool Color4::operator== (const Color4& other) const {
|
||||
return ( r == other.r && g == other.g && b == other.b && a == other.a);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline bool Color4::operator!= (const Color4& other) const {
|
||||
return ( r != other.r || g != other.g || b != other.b || a != other.a);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Color4 Color4::operator+ (const Color4& other) const {
|
||||
return Color4(r + other.r, g + other.g, b + other.b, a + other.a);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Color4 Color4::operator- (const Color4& other) const {
|
||||
return Color4(r - other.r, g - other.g, b - other.b, a - other.a);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline Color4 Color4::operator* (float fScalar) const {
|
||||
return Color4(fScalar * r, fScalar * g, fScalar * b, fScalar * a);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline Color4 Color4::operator- () const {
|
||||
return Color4(-r, -g, -b, -a);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline Color4 operator* (float fScalar, const Color4& other) {
|
||||
return Color4(fScalar * other.r, fScalar * other.g,
|
||||
fScalar * other.b, fScalar * other.a);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline Color4& Color4::operator+= (const Color4& other) {
|
||||
r += other.r;
|
||||
g += other.g;
|
||||
b += other.b;
|
||||
a += other.a;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline Color4& Color4::operator-= (const Color4& other) {
|
||||
r -= other.r;
|
||||
g -= other.g;
|
||||
b -= other.b;
|
||||
a -= other.a;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline Color4& Color4::operator*= (float fScalar) {
|
||||
r *= fScalar;
|
||||
g *= fScalar;
|
||||
b *= fScalar;
|
||||
a *= fScalar;
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
template <>
|
||||
struct HashTrait<G3D::Color4> {
|
||||
static size_t hashCode(const G3D::Color4& key) {
|
||||
return key.hashCode();
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
115
dep/include/g3dlite/G3D/Color4uint8.h
Normal file
115
dep/include/g3dlite/G3D/Color4uint8.h
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
/**
|
||||
@file Color4uint8.h
|
||||
|
||||
@maintainer Morgan McGuire, graphics3d.com
|
||||
|
||||
@created 2003-04-07
|
||||
@edited 2006-03-24
|
||||
|
||||
Copyright 2000-2006, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef COLOR4UINT8_H
|
||||
#define COLOR4UINT8_H
|
||||
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Color3uint8.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
Represents a Color4 as a packed integer. Convenient
|
||||
for creating unsigned int vertex arrays. Used by
|
||||
G3D::GImage as the underlying format.
|
||||
|
||||
<B>WARNING</B>: Integer color formats are different than
|
||||
integer vertex formats. The color channels are automatically
|
||||
scaled by 255 (because OpenGL automatically scales integer
|
||||
colors back by this factor). So Color4(1,1,1) == Color4uint8(255,255,255)
|
||||
but Vector3(1,1,1) == Vector3int16(1,1,1).
|
||||
|
||||
*/
|
||||
G3D_BEGIN_PACKED_CLASS(1)
|
||||
class Color4uint8 {
|
||||
private:
|
||||
// Hidden operators
|
||||
bool operator<(const Color4uint8&) const;
|
||||
bool operator>(const Color4uint8&) const;
|
||||
bool operator<=(const Color4uint8&) const;
|
||||
bool operator>=(const Color4uint8&) const;
|
||||
|
||||
public:
|
||||
uint8 r;
|
||||
uint8 g;
|
||||
uint8 b;
|
||||
uint8 a;
|
||||
|
||||
Color4uint8() : r(0), g(0), b(0), a(0) {}
|
||||
|
||||
Color4uint8(const class Color4& c);
|
||||
|
||||
Color4uint8(const uint8 _r, const uint8 _g, const uint8 _b, const uint8 _a) : r(_r), g(_g), b(_b), a(_a) {}
|
||||
|
||||
Color4uint8(const Color3uint8& c, const uint8 _a) : r(c.r), g(c.g), b(c.b), a(_a) {}
|
||||
|
||||
Color4uint8(class BinaryInput& bi);
|
||||
|
||||
inline static Color4uint8 fromARGB(uint32 i) {
|
||||
Color4uint8 c;
|
||||
c.a = (i >> 24) & 0xFF;
|
||||
c.r = (i >> 16) & 0xFF;
|
||||
c.g = (i >> 8) & 0xFF;
|
||||
c.b = i & 0xFF;
|
||||
return c;
|
||||
}
|
||||
|
||||
inline uint32 asUInt32() const {
|
||||
return ((uint32)a << 24) + ((uint32)r << 16) + ((uint32)g << 8) + b;
|
||||
}
|
||||
|
||||
// access vector V as V[0] = V.r, V[1] = V.g, V[2] = V.b
|
||||
//
|
||||
// WARNING. These member functions rely on
|
||||
// (1) Color4uint8 not having virtual functions
|
||||
// (2) the data packed in a 3*sizeof(uint8) memory block
|
||||
uint8& operator[] (int i) const {
|
||||
return ((uint8*)this)[i];
|
||||
}
|
||||
|
||||
operator uint8* () {
|
||||
return (uint8*)this;
|
||||
}
|
||||
|
||||
operator const uint8* () const {
|
||||
return (uint8*)this;
|
||||
}
|
||||
|
||||
|
||||
inline Color3uint8 bgr() const {
|
||||
return Color3uint8(b, g, r);
|
||||
}
|
||||
|
||||
void serialize(class BinaryOutput& bo) const;
|
||||
|
||||
void deserialize(class BinaryInput& bi);
|
||||
|
||||
inline Color3uint8 rgb() const {
|
||||
return Color3uint8(r, g, b);
|
||||
}
|
||||
|
||||
bool operator==(const Color4uint8& other) const {
|
||||
return *reinterpret_cast<const uint32*>(this) == *reinterpret_cast<const uint32*>(&other);
|
||||
}
|
||||
|
||||
bool operator!=(const Color4uint8& other) const {
|
||||
return *reinterpret_cast<const uint32*>(this) != *reinterpret_cast<const uint32*>(&other);
|
||||
}
|
||||
|
||||
}
|
||||
G3D_END_PACKED_CLASS(1)
|
||||
|
||||
} // namespace G3D
|
||||
|
||||
#endif
|
||||
68
dep/include/g3dlite/G3D/Cone.h
Normal file
68
dep/include/g3dlite/G3D/Cone.h
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
/**
|
||||
@file Cone.h
|
||||
|
||||
Cone class
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
@cite Portions based on Dave Eberly's Magic Software Library at <A HREF="http://www.magic-software.com">http://www.magic-software.com</A>
|
||||
|
||||
@created 2001-06-02
|
||||
@edited 2006-02-23
|
||||
|
||||
Copyright 2000-2006, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_CONE_H
|
||||
#define G3D_CONE_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/Vector3.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
An infinite cone.
|
||||
*/
|
||||
class Cone {
|
||||
|
||||
private:
|
||||
Vector3 tip;
|
||||
Vector3 direction;
|
||||
|
||||
/** Angle from the center line to the edge. */
|
||||
float angle;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
@param angle Angle from the center line to the edge, in radians
|
||||
*/
|
||||
Cone(const Vector3& tip, const Vector3& direction, float angle);
|
||||
|
||||
/**
|
||||
Forms the smallest cone that contains the box. Undefined if
|
||||
the tip is inside or on the box.
|
||||
*/
|
||||
Cone(const Vector3& tip, const class Box& box);
|
||||
|
||||
virtual ~Cone() {}
|
||||
|
||||
/**
|
||||
Returns true if the cone touches, intersects, or contains b.
|
||||
|
||||
If c.intersects(s) and c.intersects(Sphere(s.center, s.radius * 2)
|
||||
then the sphere s is entirely within cone c.
|
||||
*/
|
||||
bool intersects(const class Sphere& s) const;
|
||||
|
||||
/**
|
||||
True if v is a point inside the cone.
|
||||
*/
|
||||
bool contains(const class Vector3& v) const;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
180
dep/include/g3dlite/G3D/ConvexPolyhedron.h
Normal file
180
dep/include/g3dlite/G3D/ConvexPolyhedron.h
Normal file
|
|
@ -0,0 +1,180 @@
|
|||
/**
|
||||
@file ConvexPolyhedron.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2001-11-11
|
||||
@edited 2006-04-10
|
||||
|
||||
Copyright 2000-2006, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_CONVEXPOLYHEDRON_H
|
||||
#define G3D_CONVEXPOLYHEDRON_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Vector3.h"
|
||||
#include "G3D/Vector2.h"
|
||||
#include "G3D/CoordinateFrame.h"
|
||||
#include "G3D/Plane.h"
|
||||
#include "G3D/Line.h"
|
||||
#include "G3D/Array.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
class DirectedEdge {
|
||||
public:
|
||||
Vector3 start;
|
||||
Vector3 stop;
|
||||
};
|
||||
|
||||
class ConvexPolygon {
|
||||
private:
|
||||
|
||||
friend class ConvexPolyhedron;
|
||||
|
||||
Array<Vector3> _vertex;
|
||||
|
||||
public:
|
||||
|
||||
ConvexPolygon() {}
|
||||
ConvexPolygon(const Vector3& v0, const Vector3& v1, const Vector3& v2);
|
||||
ConvexPolygon(const Array<Vector3>& __vertex);
|
||||
virtual ~ConvexPolygon() {}
|
||||
|
||||
/**
|
||||
Counter clockwise winding order.
|
||||
*/
|
||||
inline const Vector3& vertex(int i) const {
|
||||
return _vertex[i];
|
||||
}
|
||||
|
||||
inline void setVertex(int i, const Vector3& v) {
|
||||
_vertex[i] = v;
|
||||
}
|
||||
|
||||
/**
|
||||
Zero vertices indicates an empty polygon (zero area).
|
||||
*/
|
||||
inline int numVertices() const {
|
||||
return _vertex.size();
|
||||
}
|
||||
|
||||
inline void setNumVertices(int n) {
|
||||
_vertex.resize(n);
|
||||
}
|
||||
|
||||
/**
|
||||
O(n) in the number of edges
|
||||
*/
|
||||
bool isEmpty() const;
|
||||
|
||||
/**
|
||||
Cuts the polygon at the plane. If the polygon is entirely above or below
|
||||
the plane, one of the returned polygons will be empty.
|
||||
|
||||
@param above The part of the polygon above (on the side the
|
||||
normal points to or in the plane) the plane
|
||||
@param below The part of the polygon below the plane.
|
||||
@param newEdge If a new edge was introduced, this is that edge (on the above portion; the below portion is the opposite winding.
|
||||
*/
|
||||
void cut(const Plane& plane, ConvexPolygon &above, ConvexPolygon &below, DirectedEdge& newEdge);
|
||||
void cut(const Plane& plane, ConvexPolygon &above, ConvexPolygon &below);
|
||||
|
||||
/**
|
||||
When a cut plane grazes a vertex in the polygon, two near-identical vertices may be created.
|
||||
The closeness of these two points can cause a number of problems, such as ConvexPolygon::normal()
|
||||
returning an infinite vector. It should be noted, however, that not all applications are
|
||||
sensitive to near-identical vertices.
|
||||
|
||||
removeDuplicateVertices() detects and eliminates redundant vertices.
|
||||
*/
|
||||
void removeDuplicateVertices();
|
||||
|
||||
/**
|
||||
O(n) in the number of edges
|
||||
*/
|
||||
float getArea() const;
|
||||
|
||||
inline Vector3 normal() const {
|
||||
debugAssert(_vertex.length() >= 3);
|
||||
return (_vertex[1] - _vertex[0]).cross(_vertex[2] - _vertex[0]).direction();
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the same polygon with inverse winding.
|
||||
*/
|
||||
ConvexPolygon inverse() const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class ConvexPolyhedron {
|
||||
public:
|
||||
/**
|
||||
Zero faces indicates an empty polyhedron
|
||||
*/
|
||||
Array<ConvexPolygon> face;
|
||||
|
||||
ConvexPolyhedron() {}
|
||||
ConvexPolyhedron(const Array<ConvexPolygon>& _face);
|
||||
|
||||
/**
|
||||
O(n) in the number of edges
|
||||
*/
|
||||
bool isEmpty() const;
|
||||
|
||||
/**
|
||||
O(n) in the number of edges
|
||||
*/
|
||||
float getVolume() const;
|
||||
|
||||
/**
|
||||
Cuts the polyhedron at the plane. If the polyhedron is entirely above or below
|
||||
the plane, one of the returned polyhedra will be empty.
|
||||
|
||||
@param above The part of the polyhedron above (on the side the
|
||||
normal points to or in the plane) the plane
|
||||
@param below The part of the polyhedron below the plane.
|
||||
*/
|
||||
void cut(const Plane& plane, ConvexPolyhedron &above, ConvexPolyhedron &below);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
*/
|
||||
class ConvexPolygon2D {
|
||||
private:
|
||||
|
||||
Array<Vector2> m_vertex;
|
||||
|
||||
public:
|
||||
|
||||
ConvexPolygon2D() {}
|
||||
|
||||
/**
|
||||
Points are counter-clockwise in a Y = down, X = right coordinate
|
||||
system.
|
||||
|
||||
@param reverse If true, the points are reversed (i.e. winding direction is changed)
|
||||
before the polygon is created.
|
||||
*/
|
||||
ConvexPolygon2D(const Array<Vector2>& pts, bool reverse = false);
|
||||
|
||||
inline int numVertices() const {
|
||||
return m_vertex.size();
|
||||
}
|
||||
|
||||
inline const Vector2& vertex(int index) const {
|
||||
debugAssert((index >= 0) && (index <= m_vertex.size()));
|
||||
return m_vertex[index];
|
||||
}
|
||||
|
||||
/** @param reverseWinding If true, the winding direction of the polygon is reversed for this test.*/
|
||||
bool contains(const Vector2& p, bool reverseWinding = false) const;
|
||||
};
|
||||
|
||||
|
||||
} // namespace
|
||||
#endif
|
||||
|
|
@ -1,17 +1,17 @@
|
|||
/**
|
||||
@file CoordinateFrame.h
|
||||
|
||||
@maintainer Morgan McGuire, matrix@graphics3d.com
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2001-03-04
|
||||
@edited 2006-04-07
|
||||
@edited 2009-04-29
|
||||
|
||||
Copyright 2000-2006, Morgan McGuire.
|
||||
Copyright 2000-2009, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_COORDINATEFRAME_H
|
||||
#define G3D_COORDINATEFRAME_H
|
||||
#ifndef G3D_CFrame_h
|
||||
#define G3D_CFrame_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Vector3.h"
|
||||
|
|
@ -24,7 +24,15 @@
|
|||
#include <cstdarg>
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Turn off "conditional expression is constant" warning; MSVC generates this
|
||||
// for debug assertions in inlined methods.
|
||||
# pragma warning (disable : 4127)
|
||||
#endif
|
||||
|
||||
|
||||
namespace G3D {
|
||||
class Any;
|
||||
|
||||
/**
|
||||
A rigid body RT (rotation-translation) transformation.
|
||||
|
|
@ -45,26 +53,26 @@ Convert to Matrix4 using CoordinateFrame::toMatrix4. You <I>can</I> construct a
|
|||
from a Matrix4 using Matrix4::approxCoordinateFrame, however, because a Matrix4 is more
|
||||
general than a CoordinateFrame, some information may be lost.
|
||||
|
||||
See also: G3D::Matrix4, G3D::Quat
|
||||
@sa G3D::UprightFrame, G3D::PhysicsFrame, G3D::Matrix4, G3D::Quat
|
||||
*/
|
||||
class CoordinateFrame {
|
||||
public:
|
||||
|
||||
/**
|
||||
Takes object space points to world space.
|
||||
*/
|
||||
/** Takes object space points to world space. */
|
||||
Matrix3 rotation;
|
||||
|
||||
/**
|
||||
Takes object space points to world space.
|
||||
*/
|
||||
/** Takes object space points to world space. */
|
||||
Vector3 translation;
|
||||
|
||||
/**
|
||||
The direction an object "looks" relative to its own axes.
|
||||
@deprecated This is always -1 and will be fixed at that value in future releases.
|
||||
*/
|
||||
static const float zLookDirection;
|
||||
/** \param any Must be in one of the following forms:
|
||||
- CFrame((matrix3 expr), (vector3 expr))
|
||||
- CFrame::fromXYZYPRDegrees(#, #, #, #, #, #)
|
||||
- CFrame { rotation = (matrix3 expr), translation = (vector3 expr) }
|
||||
*/
|
||||
CoordinateFrame(const Any& any);
|
||||
|
||||
/** Converts the CFrame to an Any. */
|
||||
operator Any() const;
|
||||
|
||||
inline bool operator==(const CoordinateFrame& other) const {
|
||||
return (translation == other.translation) && (rotation == other.rotation);
|
||||
|
|
@ -83,14 +91,12 @@ public:
|
|||
/**
|
||||
Initializes to the identity coordinate frame.
|
||||
*/
|
||||
inline CoordinateFrame() :
|
||||
rotation(Matrix3::identity()), translation(Vector3::zero()) {
|
||||
}
|
||||
CoordinateFrame();
|
||||
|
||||
CoordinateFrame(const Vector3& _translation) :
|
||||
CoordinateFrame(const Vector3& _translation) :
|
||||
rotation(Matrix3::identity()), translation(_translation) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CoordinateFrame(const Matrix3 &rotation, const Vector3 &translation) :
|
||||
rotation(rotation), translation(translation) {
|
||||
}
|
||||
|
|
@ -99,6 +105,23 @@ public:
|
|||
rotation(rotation), translation(Vector3::zero()) {
|
||||
}
|
||||
|
||||
CoordinateFrame(const class UprightFrame& f);
|
||||
|
||||
static CoordinateFrame fromXYZYPRRadians(float x, float y, float z, float yaw = 0.0f, float pitch = 0.0f, float roll = 0.0f);
|
||||
|
||||
/** Construct a coordinate frame from translation = (x,y,z) and
|
||||
rotations (in that order) about Y, object space X, object space
|
||||
Z. Note that because object-space axes are used, these are not
|
||||
equivalent to Euler angles; they are known as Tait-Bryan
|
||||
rotations and are more convenient for intuitive positioning.*/
|
||||
static CoordinateFrame fromXYZYPRDegrees(float x, float y, float z, float yaw = 0.0f, float pitch = 0.0f, float roll = 0.0f);
|
||||
|
||||
CoordinateFrame(class BinaryInput& b);
|
||||
|
||||
void deserialize(class BinaryInput& b);
|
||||
|
||||
void serialize(class BinaryOutput& b) const;
|
||||
|
||||
CoordinateFrame(const CoordinateFrame &other) :
|
||||
rotation(other.rotation), translation(other.translation) {}
|
||||
|
||||
|
|
@ -117,8 +140,13 @@ public:
|
|||
/** See also Matrix4::approxCoordinateFrame */
|
||||
class Matrix4 toMatrix4() const;
|
||||
|
||||
void getXYZYPRRadians(float& x, float& y, float& z, float& yaw, float& pitch, float& roll) const;
|
||||
void getXYZYPRDegrees(float& x, float& y, float& z, float& yaw, float& pitch, float& roll) const;
|
||||
|
||||
|
||||
/**
|
||||
Produces an XML serialization of this coordinate frame.
|
||||
@deprecated
|
||||
*/
|
||||
std::string toXML() const;
|
||||
|
||||
|
|
@ -131,7 +159,7 @@ public:
|
|||
object has an inverted heading.
|
||||
*/
|
||||
inline float getHeading() const {
|
||||
Vector3 look = rotation.getColumn(2);
|
||||
Vector3 look = rotation.column(2);
|
||||
float angle = -(float) atan2(-look.x, look.z);
|
||||
return angle;
|
||||
}
|
||||
|
|
@ -163,17 +191,18 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
Transforms the point into object space.
|
||||
Transforms the point into object space. Assumes that the rotation matrix is orthonormal.
|
||||
*/
|
||||
inline Vector3 pointToObjectSpace(const Vector3& v) const {
|
||||
float p[3];
|
||||
p[0] = v[0] - translation[0];
|
||||
p[1] = v[1] - translation[1];
|
||||
p[2] = v[2] - translation[2];
|
||||
return Vector3(
|
||||
rotation[0][0] * p[0] + rotation[1][0] * p[1] + rotation[2][0] * p[2],
|
||||
rotation[0][1] * p[0] + rotation[1][1] * p[1] + rotation[2][1] * p[2],
|
||||
rotation[0][2] * p[0] + rotation[1][2] * p[1] + rotation[2][2] * p[2]);
|
||||
inline Vector3 pointToObjectSpace(const Vector3& v) const {
|
||||
float p[3];
|
||||
p[0] = v[0] - translation[0];
|
||||
p[1] = v[1] - translation[1];
|
||||
p[2] = v[2] - translation[2];
|
||||
debugAssert(G3D::fuzzyEq(rotation.determinant(), 1.0f));
|
||||
return Vector3(
|
||||
rotation[0][0] * p[0] + rotation[1][0] * p[1] + rotation[2][0] * p[2],
|
||||
rotation[0][1] * p[0] + rotation[1][1] * p[1] + rotation[2][1] * p[2],
|
||||
rotation[0][2] * p[0] + rotation[1][2] * p[1] + rotation[2][2] * p[2]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -260,14 +289,9 @@ public:
|
|||
const Vector3& target,
|
||||
Vector3 up);
|
||||
|
||||
/** @deprecated See lookVector */
|
||||
inline Vector3 getLookVector() const {
|
||||
return rotation.getColumn(2) * zLookDirection;
|
||||
}
|
||||
|
||||
/** The direction this camera is looking (its negative z axis)*/
|
||||
inline Vector3 lookVector() const {
|
||||
return rotation.getColumn(2) * zLookDirection;
|
||||
return -rotation.column(2);
|
||||
}
|
||||
|
||||
/** Returns the ray starting at the camera origin travelling in direction CoordinateFrame::lookVector. */
|
||||
|
|
@ -275,20 +299,11 @@ public:
|
|||
|
||||
/** Up direction for this camera (its y axis). */
|
||||
inline Vector3 upVector() const {
|
||||
return rotation.getColumn(1);
|
||||
return rotation.column(1);
|
||||
}
|
||||
|
||||
/**
|
||||
If a viewer looks along the look vector, this is the viewer's "left"
|
||||
@deprecated leftVector
|
||||
*/
|
||||
inline Vector3 getLeftVector() const {
|
||||
return -rotation.getColumn(0);
|
||||
}
|
||||
|
||||
/** @deprecated See rightVector */
|
||||
inline Vector3 getRightVector() const {
|
||||
return rotation.getColumn(0);
|
||||
inline Vector3 rightVector() const {
|
||||
return rotation.column(0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -296,11 +311,7 @@ public:
|
|||
Useful for strafing motions and building alternative coordinate frames.
|
||||
*/
|
||||
inline Vector3 leftVector() const {
|
||||
return -rotation.getColumn(0);
|
||||
}
|
||||
|
||||
inline Vector3 rightVector() const {
|
||||
return rotation.getColumn(0);
|
||||
return -rotation.column(0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -313,6 +324,8 @@ public:
|
|||
|
||||
};
|
||||
|
||||
typedef CoordinateFrame CFrame;
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/**
|
||||
@file Crypto.h
|
||||
|
||||
@maintainer Morgan McGuire, matrix@graphics3d.com
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
|
||||
@created 2006-03-29
|
||||
|
|
@ -17,6 +17,48 @@
|
|||
|
||||
namespace G3D {
|
||||
|
||||
/** See G3D::Crypto::md5 */
|
||||
class MD5Hash {
|
||||
private:
|
||||
|
||||
uint8 value[16];
|
||||
|
||||
public:
|
||||
|
||||
MD5Hash() {
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
value[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
explicit MD5Hash(class BinaryInput& b);
|
||||
|
||||
uint8& operator[](int i) {
|
||||
return value[i];
|
||||
}
|
||||
|
||||
const uint8& operator[](int i) const {
|
||||
return value[i];
|
||||
}
|
||||
|
||||
bool operator==(const MD5Hash& other) const {
|
||||
bool match = true;
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
match = match && (other.value[i] == value[i]);
|
||||
}
|
||||
return match;
|
||||
}
|
||||
|
||||
inline bool operator!=(const MD5Hash& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
void deserialize(class BinaryInput& b);
|
||||
|
||||
void serialize(class BinaryOutput& b) const;
|
||||
};
|
||||
|
||||
|
||||
/** Cryptography and hashing helper functions */
|
||||
class Crypto {
|
||||
public:
|
||||
|
|
@ -31,6 +73,14 @@ public:
|
|||
*/
|
||||
static uint32 crc32(const void* bytes, size_t numBytes);
|
||||
|
||||
/**
|
||||
Computes the MD5 hash (message digest) of a byte stream, as defined by
|
||||
http://www.ietf.org/rfc/rfc1321.txt.
|
||||
|
||||
@cite Based on implementation by L. Peter Deutsch, ghost@aladdin.com
|
||||
*/
|
||||
MD5Hash md5(const void* bytes, size_t numBytes);
|
||||
|
||||
/**
|
||||
Returns the nth prime less than 2000 in constant time. The first prime has index
|
||||
0 and is the number 2.
|
||||
|
|
|
|||
92
dep/include/g3dlite/G3D/Cylinder.h
Normal file
92
dep/include/g3dlite/G3D/Cylinder.h
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
/**
|
||||
@file Cylinder.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2003-02-07
|
||||
@edited 2005-09-26
|
||||
|
||||
Copyright 2000-2005, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_Cylinder_H
|
||||
#define G3D_Cylinder_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/Vector3.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
class Line;
|
||||
class AABox;
|
||||
/**
|
||||
Right cylinder
|
||||
*/
|
||||
class Cylinder {
|
||||
private:
|
||||
Vector3 p1;
|
||||
Vector3 p2;
|
||||
|
||||
float mRadius;
|
||||
|
||||
public:
|
||||
|
||||
/** Uninitialized */
|
||||
Cylinder();
|
||||
Cylinder(class BinaryInput& b);
|
||||
Cylinder(const Vector3& _p1, const Vector3& _p2, float _r);
|
||||
void serialize(class BinaryOutput& b) const;
|
||||
void deserialize(class BinaryInput& b);
|
||||
|
||||
/** The line down the center of the Cylinder */
|
||||
Line axis() const;
|
||||
|
||||
/**
|
||||
A reference frame in which the center of mass is at the origin and
|
||||
the Y-axis is the cylinder's axis. If the cylinder is transformed, this reference frame
|
||||
may freely rotate around its axis.*/
|
||||
void getReferenceFrame(class CoordinateFrame& cframe) const;
|
||||
|
||||
/** Returns point 0 or 1 */
|
||||
inline const Vector3& point(int i) const {
|
||||
debugAssert(i >= 0 && i <= 1);
|
||||
return (i == 0) ? p1 : p2;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns true if the point is inside the Cylinder or on its surface.
|
||||
*/
|
||||
bool contains(const Vector3& p) const;
|
||||
|
||||
float area() const;
|
||||
|
||||
float volume() const;
|
||||
|
||||
float radius() const;
|
||||
|
||||
/** Center of mass */
|
||||
inline Vector3 center() const {
|
||||
return (p1 + p2) / 2.0f;
|
||||
}
|
||||
|
||||
inline float height() const {
|
||||
return (p1 - p2).magnitude();
|
||||
}
|
||||
|
||||
/**
|
||||
Get close axis aligned bounding box.
|
||||
With vertical world orientation, the top and bottom might not be very tight. */
|
||||
void getBounds(AABox& out) const;
|
||||
|
||||
/** Random world space point with outward facing normal. */
|
||||
void getRandomSurfacePoint(Vector3& P, Vector3& N) const;
|
||||
|
||||
/** Point selected uniformly at random over the volume. */
|
||||
Vector3 randomInteriorPoint() const;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
26
dep/include/g3dlite/G3D/EqualsTrait.h
Normal file
26
dep/include/g3dlite/G3D/EqualsTrait.h
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/**
|
||||
@file EqualsTrait.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
@created 2008-10-01
|
||||
@edited 2008-10-01
|
||||
Copyright 2000-2009, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_EQUALSTRAIT_H
|
||||
#define G3D_EQUALSTRAIT_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
|
||||
/** Default implementation of EqualsTrait.
|
||||
@see G3D::Table for specialization requirements.
|
||||
*/
|
||||
template<typename Key> struct EqualsTrait {
|
||||
static bool equals(const Key& a, const Key& b) {
|
||||
return a == b;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
162
dep/include/g3dlite/G3D/G3D.h
Normal file
162
dep/include/g3dlite/G3D/G3D.h
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
/**
|
||||
@file G3D.h
|
||||
|
||||
This header includes all of the G3D libraries in
|
||||
appropriate namespaces.
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2001-08-25
|
||||
@edited 2010-01-30
|
||||
|
||||
Copyright 2000-2010, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_G3D_h
|
||||
#define G3D_G3D_h
|
||||
|
||||
#define NOMINMAX 1
|
||||
#ifdef min
|
||||
#undef min
|
||||
#endif
|
||||
#ifdef max
|
||||
#undef max
|
||||
#endif
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/units.h"
|
||||
#include "G3D/ParseError.h"
|
||||
#include "G3D/Random.h"
|
||||
#include "G3D/Array.h"
|
||||
#include "G3D/SmallArray.h"
|
||||
#include "G3D/Queue.h"
|
||||
#include "G3D/Crypto.h"
|
||||
#include "G3D/format.h"
|
||||
#include "G3D/Vector2.h"
|
||||
#include "G3D/Vector3.h"
|
||||
#include "G3D/Vector4.h"
|
||||
#include "G3D/Color1.h"
|
||||
#include "G3D/Color3.h"
|
||||
#include "G3D/Color4.h"
|
||||
#include "G3D/Matrix2.h"
|
||||
#include "G3D/Matrix3.h"
|
||||
#include "G3D/Matrix4.h"
|
||||
#include "G3D/CoordinateFrame.h"
|
||||
#include "G3D/PhysicsFrame.h"
|
||||
#include "G3D/Plane.h"
|
||||
#include "G3D/Line.h"
|
||||
#include "G3D/Ray.h"
|
||||
#include "G3D/Sphere.h"
|
||||
#include "G3D/Box.h"
|
||||
#include "G3D/Box2D.h"
|
||||
#include "G3D/AABox.h"
|
||||
#include "G3D/WrapMode.h"
|
||||
#include "G3D/Cone.h"
|
||||
#include "G3D/Quat.h"
|
||||
#include "G3D/stringutils.h"
|
||||
#include "G3D/prompt.h"
|
||||
#include "G3D/Table.h"
|
||||
#include "G3D/Set.h"
|
||||
#include "G3D/GUniqueID.h"
|
||||
#include "G3D/BinaryFormat.h"
|
||||
#include "G3D/BinaryInput.h"
|
||||
#include "G3D/BinaryOutput.h"
|
||||
#include "G3D/debug.h"
|
||||
#include "G3D/g3dfnmatch.h"
|
||||
#include "G3D/G3DGameUnits.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/uint128.h"
|
||||
#include "G3D/fileutils.h"
|
||||
#include "G3D/ReferenceCount.h"
|
||||
#include "G3D/Welder.h"
|
||||
#include "G3D/GMutex.h"
|
||||
#include "G3D/PrecomputedRandom.h"
|
||||
#include "G3D/MemoryManager.h"
|
||||
#include "G3D/AreaMemoryManager.h"
|
||||
#include "G3D/BumpMapPreprocess.h"
|
||||
|
||||
template<class T> struct HashTrait< G3D::ReferenceCountedPointer<T> > {
|
||||
static size_t hashCode(G3D::ReferenceCountedPointer<T> key) { return reinterpret_cast<size_t>( key.pointer() ); }
|
||||
};
|
||||
|
||||
#include "G3D/GImage.h"
|
||||
#include "G3D/CollisionDetection.h"
|
||||
#include "G3D/Intersect.h"
|
||||
#include "G3D/Log.h"
|
||||
#include "G3D/serialize.h"
|
||||
#include "G3D/TextInput.h"
|
||||
#include "G3D/NetAddress.h"
|
||||
#include "G3D/NetworkDevice.h"
|
||||
#include "G3D/System.h"
|
||||
#include "G3D/splinefunc.h"
|
||||
#include "G3D/Spline.h"
|
||||
#include "G3D/UprightFrame.h"
|
||||
#include "G3D/LineSegment.h"
|
||||
#include "G3D/Capsule.h"
|
||||
#include "G3D/Cylinder.h"
|
||||
#include "G3D/Triangle.h"
|
||||
#include "G3D/Color3uint8.h"
|
||||
#include "G3D/Color4uint8.h"
|
||||
#include "G3D/Vector2int16.h"
|
||||
#include "G3D/Vector3int16.h"
|
||||
#include "G3D/Vector3int32.h"
|
||||
#include "G3D/Vector4int8.h"
|
||||
#include "G3D/ConvexPolyhedron.h"
|
||||
#include "G3D/MeshAlg.h"
|
||||
#include "G3D/vectorMath.h"
|
||||
#include "G3D/Rect2D.h"
|
||||
#include "G3D/GCamera.h"
|
||||
#include "G3D/GLight.h"
|
||||
#include "G3D/KDTree.h"
|
||||
#include "G3D/PointKDTree.h"
|
||||
#include "G3D/TextOutput.h"
|
||||
#include "G3D/MeshBuilder.h"
|
||||
#include "G3D/Stopwatch.h"
|
||||
#include "G3D/AtomicInt32.h"
|
||||
#include "G3D/GThread.h"
|
||||
#include "G3D/ThreadSet.h"
|
||||
#include "G3D/RegistryUtil.h"
|
||||
#include "G3D/Any.h"
|
||||
#include "G3D/PointHashGrid.h"
|
||||
#include "G3D/Map2D.h"
|
||||
#include "G3D/Image1.h"
|
||||
#include "G3D/Image1uint8.h"
|
||||
#include "G3D/Image3.h"
|
||||
#include "G3D/Image3uint8.h"
|
||||
#include "G3D/Image4.h"
|
||||
#include "G3D/Image4uint8.h"
|
||||
#include "G3D/filter.h"
|
||||
#include "G3D/WeakCache.h"
|
||||
#include "G3D/Pointer.h"
|
||||
#include "G3D/Matrix.h"
|
||||
#include "G3D/ImageFormat.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma comment(lib, "zlib")
|
||||
# pragma comment(lib, "ws2_32")
|
||||
# pragma comment(lib, "winmm")
|
||||
# pragma comment(lib, "imagehlp")
|
||||
# pragma comment(lib, "gdi32")
|
||||
# pragma comment(lib, "user32")
|
||||
# pragma comment(lib, "kernel32")
|
||||
# pragma comment(lib, "version")
|
||||
# pragma comment(lib, "advapi32")
|
||||
# pragma comment(lib, "png")
|
||||
# pragma comment(lib, "jpeg")
|
||||
# pragma comment(lib, "zip")
|
||||
# ifdef _DEBUG
|
||||
// Don't link against G3D when building G3D itself.
|
||||
# ifndef G3D_BUILDING_LIBRARY_DLL
|
||||
# pragma comment(lib, "G3Dd.lib")
|
||||
# endif
|
||||
# else
|
||||
// Don't link against G3D when building G3D itself.
|
||||
# ifndef G3D_BUILDING_LIBRARY_DLL
|
||||
# pragma comment(lib, "G3D.lib")
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
26
dep/include/g3dlite/G3D/G3DAll.h
Normal file
26
dep/include/g3dlite/G3D/G3DAll.h
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/**
|
||||
@file G3DAll.h
|
||||
|
||||
Includes all G3D and GLG3D files and uses the G3D namespace.
|
||||
|
||||
This requires OpenGL and SDL headers. If you don't want all of this,
|
||||
\#include <G3D.h> separately.
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2002-01-01
|
||||
@edited 2006-08-13
|
||||
|
||||
Copyright 2000-2006, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_G3DALL_H
|
||||
#define G3D_G3DALL_H
|
||||
|
||||
#include "G3D/G3D.h"
|
||||
#include "GLG3D/GLG3D.h"
|
||||
|
||||
using namespace G3D;
|
||||
|
||||
#endif
|
||||
42
dep/include/g3dlite/G3D/G3DGameUnits.h
Normal file
42
dep/include/g3dlite/G3D/G3DGameUnits.h
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
@file G3DGameUnits.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
@created 2002-10-05
|
||||
@edited 2006-11-10
|
||||
*/
|
||||
|
||||
#ifndef G3D_GAMEUNITS_H
|
||||
#define G3D_GAMEUNITS_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
|
||||
namespace G3D {
|
||||
/**
|
||||
Time, in seconds.
|
||||
*/
|
||||
typedef double GameTime;
|
||||
typedef double SimTime;
|
||||
|
||||
/**
|
||||
Actual wall clock time in seconds.
|
||||
*/
|
||||
typedef double RealTime;
|
||||
|
||||
enum AMPM {AM, PM};
|
||||
|
||||
/** \deprecated */
|
||||
enum {SECOND=1, MINUTE=60, HOUR = 60*60, DAY=24*60*60, SUNRISE=24*60*60/4, SUNSET=24*60*60*3/4, MIDNIGHT=0, METER=1, KILOMETER=1000};
|
||||
|
||||
/**
|
||||
Converts a 12 hour clock time into the number of seconds since
|
||||
midnight. Note that 12:00 PM is noon and 12:00 AM is midnight.
|
||||
|
||||
Example: <CODE>toSeconds(10, 00, AM)</CODE>
|
||||
*/
|
||||
SimTime toSeconds(int hour, int minute, double seconds, AMPM ap);
|
||||
SimTime toSeconds(int hour, int minute, AMPM ap);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -1,58 +1,87 @@
|
|||
/**
|
||||
@file GCamera.h
|
||||
|
||||
@maintainer Morgan McGuire, matrix@graphics3d.com
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2001-06-02
|
||||
@edited 2006-02-11
|
||||
@created 2005-07-20
|
||||
@edited 2009-04-20
|
||||
*/
|
||||
|
||||
#ifndef G3D_GCAMERA_H
|
||||
#define G3D_GCAMERA_H
|
||||
#ifndef G3D_GCamera_H
|
||||
#define G3D_GCamera_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/CoordinateFrame.h"
|
||||
#include "G3D/Vector3.h"
|
||||
#include "G3D/Plane.h"
|
||||
#include "G3D/debugAssert.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
class Matrix4;
|
||||
class Rect2D;
|
||||
class Any;
|
||||
|
||||
/**
|
||||
There is a viewport of width x height size in world space that corresponds to
|
||||
a screenWidth x screenHeight pixel grid on a
|
||||
renderDevice->getWidth() x renderDevice->getHeight()
|
||||
window.
|
||||
Abstraction of a pinhole camera.
|
||||
|
||||
The area a camera sees is called a frustum. It is bounded by the
|
||||
near plane, the far plane, and the sides of the view frame projected
|
||||
into the scene. It has the shape of a pyramid with the top cut off.
|
||||
|
||||
Cameras can project points from 3D to 2D. The "unit" projection
|
||||
matches OpenGL. It maps the entire view frustum to a cube of unit
|
||||
radius (i.e., edges of length 2) centered at the origin. The
|
||||
non-unit projection then maps that cube to the specified pixel
|
||||
viewport in X and Y and the range [0, 1] in Z. The projection is
|
||||
reversable as long as the projected Z value is known.
|
||||
|
||||
All viewport arguments are the pixel bounds of the viewport-- e.g.,
|
||||
RenderDevice::getViewport().
|
||||
RenderDevice::viewport().
|
||||
*/
|
||||
class GCamera {
|
||||
private:
|
||||
|
||||
/**
|
||||
Vertical field of view (in radians)
|
||||
*/
|
||||
float fieldOfView;
|
||||
|
||||
/**
|
||||
The image plane depth corresponding to a vertical field of
|
||||
view, where the film size is 1x1.
|
||||
*/
|
||||
float imagePlaneDepth;
|
||||
|
||||
/**
|
||||
Clipping plane, *not* imaging plane. Positive numbers.
|
||||
*/
|
||||
float nearPlane;
|
||||
|
||||
/**
|
||||
Positive
|
||||
*/
|
||||
float farPlane;
|
||||
|
||||
CoordinateFrame cframe;
|
||||
|
||||
public:
|
||||
/**
|
||||
Stores the direction of the field of view
|
||||
*/
|
||||
enum FOVDirection {HORIZONTAL, VERTICAL};
|
||||
|
||||
private:
|
||||
|
||||
/** Full field of view (in radians) */
|
||||
float m_fieldOfView;
|
||||
|
||||
/** Clipping plane, *not* imaging plane. Negative numbers. */
|
||||
float m_nearPlaneZ;
|
||||
|
||||
/** Negative */
|
||||
float m_farPlaneZ;
|
||||
|
||||
/** Stores the camera's location and orientation */
|
||||
CoordinateFrame m_cframe;
|
||||
|
||||
/** Horizontal or Vertical */
|
||||
FOVDirection m_direction;
|
||||
|
||||
public:
|
||||
|
||||
/** Must be of the format produced by the Any cast, e.g.,
|
||||
|
||||
<pre>
|
||||
GCamera {
|
||||
coordinateFrame = CFrame::fromXYZYPRDegrees(-13.3f, 8.0f, -1.9f, 246.6f, -3),
|
||||
nearPlaneZ = -0.5,
|
||||
farPlaneZ = -50,
|
||||
fovDirection = "HORIZONTAL",
|
||||
fovAngleDegrees = 90
|
||||
}</pre>
|
||||
|
||||
Missing fields are filled from the default GCamera constructor.
|
||||
*/
|
||||
GCamera(const Any& any);
|
||||
|
||||
operator Any() const;
|
||||
|
||||
class Frustum {
|
||||
public:
|
||||
|
|
@ -77,53 +106,97 @@ public:
|
|||
Array<Face> faceArray;
|
||||
};
|
||||
|
||||
GCamera();
|
||||
GCamera();
|
||||
|
||||
GCamera(const Matrix4& proj, const CFrame& frame);
|
||||
|
||||
virtual ~GCamera();
|
||||
|
||||
/** Returns the current coordinate frame */
|
||||
const CoordinateFrame& coordinateFrame() const {
|
||||
return m_cframe;
|
||||
}
|
||||
|
||||
CoordinateFrame getCoordinateFrame() const;
|
||||
void getCoordinateFrame(CoordinateFrame& c) const;
|
||||
void setCoordinateFrame(const CoordinateFrame& c);
|
||||
/** Sets c to the camera's coordinate frame */
|
||||
void getCoordinateFrame(CoordinateFrame& c) const;
|
||||
|
||||
/** Sets a new coordinate frame for the camera */
|
||||
void setCoordinateFrame(const CoordinateFrame& c);
|
||||
|
||||
/**
|
||||
Sets the horizontal field of view, in radians. The
|
||||
initial angle is toRadians(55).
|
||||
<UL>
|
||||
<LI> toRadians(50) - Telephoto
|
||||
<LI> toRadians(110) - Normal
|
||||
<LI> toRadians(140) - Wide angle
|
||||
</UL>
|
||||
*/
|
||||
void setFieldOfView(float angle);
|
||||
/** Sets \a P equal to the camera's projection matrix. This is the
|
||||
matrix that maps points to the homogeneous clip cube that
|
||||
varies from -1 to 1 on all axes. The projection matrix does
|
||||
not include the camera transform.
|
||||
|
||||
/**
|
||||
Sets the field of view based on a desired image plane depth
|
||||
(<I>s'</I>) and film dimensions in world space. Depth must be positive. Width,
|
||||
depth, and height are measured in the same units (meters are
|
||||
recommended). The field of view will span the diagonal to the
|
||||
image.<P> <I>Note</I>: to simulate a 35mm GCamera, set width =
|
||||
0.36 mm and height = 0.24 mm. The width and height used are
|
||||
generally not the pixel dimensions of the image.
|
||||
*/
|
||||
void setImagePlaneDepth(
|
||||
float depth,
|
||||
const class Rect2D& viewport);
|
||||
This is the matrix that a RenderDevice (or OpenGL) uses as the projection matrix.
|
||||
@sa RenderDevice::setProjectionAndCameraMatrix, RenderDevice::setProjectionMatrix, Matrix4::perspectiveProjection
|
||||
*/
|
||||
void getProjectUnitMatrix(const Rect2D& viewport, Matrix4& P) const;
|
||||
|
||||
inline double getFieldOfView() const {
|
||||
return fieldOfView;
|
||||
}
|
||||
/** Sets \a P equal to the matrix that transforms points to pixel
|
||||
coordinates on the given viewport. A point correspoinding to
|
||||
the top-left corner of the viewport in camera space will
|
||||
transform to viewport.x0y0() and the bottom-right to viewport.x1y1(). */
|
||||
void getProjectPixelMatrix(const Rect2D& viewport, Matrix4& P) const;
|
||||
|
||||
/** Converts projected points from OpenGL standards
|
||||
(-1, 1) to normal 3D coordinate standards (0, 1)
|
||||
|
||||
\deprecated
|
||||
*/ // TODO: Remove
|
||||
Vector3 convertFromUnitToNormal(const Vector3& in, const Rect2D& viewport) const;
|
||||
|
||||
/**
|
||||
Sets the field of view, in radians. The
|
||||
initial angle is toRadians(55). Must specify
|
||||
the direction of the angle.
|
||||
|
||||
This is the full angle, i.e., from the left side of the
|
||||
viewport to the right side.
|
||||
*/
|
||||
void setFieldOfView(float angle, FOVDirection direction);
|
||||
|
||||
/** Returns the current full field of view angle (from the left side of the
|
||||
viewport to the right side) and direction */
|
||||
inline void getFieldOfView(float& angle, FOVDirection& direction) const {
|
||||
angle = m_fieldOfView;
|
||||
direction = m_direction;
|
||||
}
|
||||
|
||||
/**
|
||||
Projects a world space point onto a width x height screen. The
|
||||
returned coordinate uses pixmap addressing: x = right and y =
|
||||
down. The resulting z value is <I>rhw</I>.
|
||||
down. The resulting z value is 0 at the near plane, 1 at the far plane,
|
||||
and is a linear compression of unit cube projection.
|
||||
|
||||
If the point is behind the camera, Vector3::inf() is returned.
|
||||
*/
|
||||
G3D::Vector3 project(
|
||||
const G3D::Vector3& point,
|
||||
const class Rect2D& viewport) const;
|
||||
Vector3 project(const G3D::Vector3& point,
|
||||
const class Rect2D& viewport) const;
|
||||
|
||||
/**
|
||||
Projects a world space point onto a unit cube. The resulting
|
||||
x,y,z values range between -1 and 1, where z is -1
|
||||
at the near plane and 1 at the far plane and varies hyperbolically in between.
|
||||
|
||||
If the point is behind the camera, Vector3::inf() is returned.
|
||||
*/
|
||||
Vector3 projectUnit(const G3D::Vector3& point,
|
||||
const class Rect2D& viewport) const;
|
||||
|
||||
/**
|
||||
Gives the world-space coordinates of screen space point v, where
|
||||
v.x is in pixels from the left, v.y is in pixels from
|
||||
the top, and v.z is on the range 0 (near plane) to 1 (far plane).
|
||||
*/
|
||||
Vector3 unproject(const Vector3& v, const Rect2D& viewport) const;
|
||||
|
||||
/**
|
||||
Gives the world-space coordinates of unit cube point v, where
|
||||
v varies from -1 to 1 on all axes. The unproject first
|
||||
transforms the point into a pixel location for the viewport, then calls unproject
|
||||
*/
|
||||
Vector3 unprojectUnit(const Vector3& v, const Rect2D& viewport) const;
|
||||
|
||||
/**
|
||||
Returns the pixel area covered by a shape of the given
|
||||
|
|
@ -134,24 +207,29 @@ public:
|
|||
/**
|
||||
Returns the world space 3D viewport corners. These
|
||||
are at the near clipping plane. The corners are constructed
|
||||
from the nearPlaneZ, getViewportWidth, and getViewportHeight.
|
||||
from the nearPlaneZ, viewportWidth, and viewportHeight.
|
||||
"left" and "right" are from the GCamera's perspective.
|
||||
*/
|
||||
void get3DViewportCorners(
|
||||
const class Rect2D& viewport,
|
||||
Vector3& outUR,
|
||||
Vector3& outUL,
|
||||
Vector3& outLL,
|
||||
Vector3& outLR) const;
|
||||
void getNearViewportCorners(const class Rect2D& viewport,
|
||||
Vector3& outUR, Vector3& outUL,
|
||||
Vector3& outLL, Vector3& outLR) const;
|
||||
|
||||
/**
|
||||
Returns the image plane depth, <I>s'</I>, given the current field
|
||||
of view for film of dimensions width x height. See
|
||||
setImagePlaneDepth for a discussion of worldspace values width and height.
|
||||
*/
|
||||
float getImagePlaneDepth(
|
||||
const class Rect2D& viewport) const;
|
||||
Returns the world space 3D viewport corners. These
|
||||
are at the Far clipping plane. The corners are constructed
|
||||
from the nearPlaneZ, farPlaneZ, viewportWidth, and viewportHeight.
|
||||
"left" and "right" are from the GCamera's perspective.
|
||||
*/
|
||||
void getFarViewportCorners(const class Rect2D& viewport,
|
||||
Vector3& outUR, Vector3& outUL,
|
||||
Vector3& outLL, Vector3& outLR) const;
|
||||
|
||||
/**
|
||||
Returns the image plane depth, assumes imagePlane
|
||||
is the same as the near clipping plane.
|
||||
returns a positive number.
|
||||
*/
|
||||
float imagePlaneDepth() const;
|
||||
|
||||
/**
|
||||
Returns the world space ray passing through the center of pixel
|
||||
|
|
@ -159,91 +237,99 @@ public:
|
|||
the 3D object space axes: (0,0) is the upper left corner of the screen.
|
||||
They are in viewport coordinates, not screen coordinates.
|
||||
|
||||
The ray origin is at the origin. To start it at the image plane,
|
||||
move it forward by imagePlaneDepth/ray.direction.z
|
||||
|
||||
Integer (x, y) values correspond to
|
||||
the upper left corners of pixels. If you want to cast rays
|
||||
through pixel centers, add 0.5 to x and y.
|
||||
*/
|
||||
*/
|
||||
Ray worldRay(
|
||||
float x,
|
||||
float y,
|
||||
const class Rect2D& viewport) const;
|
||||
|
||||
|
||||
/**
|
||||
Returns a negative z-value.
|
||||
*/
|
||||
inline float getNearPlaneZ() const {
|
||||
return -nearPlane;
|
||||
inline float nearPlaneZ() const {
|
||||
return m_nearPlaneZ;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a negative z-value.
|
||||
*/
|
||||
inline float getFarPlaneZ() const {
|
||||
return -farPlane;
|
||||
inline float farPlaneZ() const {
|
||||
return m_farPlaneZ;
|
||||
}
|
||||
|
||||
inline void setFarPlaneZ(float z) {
|
||||
debugAssert(z < 0);
|
||||
farPlane = -z;
|
||||
}
|
||||
|
||||
inline void setNearPlaneZ(float z) {
|
||||
debugAssert(z < 0);
|
||||
nearPlane = -z;
|
||||
}
|
||||
/**
|
||||
Sets a new value for the far clipping plane
|
||||
Expects a negative value
|
||||
*/
|
||||
inline void setFarPlaneZ(float z) {
|
||||
debugAssert(z < 0);
|
||||
m_farPlaneZ = z;
|
||||
}
|
||||
|
||||
/**
|
||||
Sets a new value for the near clipping plane
|
||||
Expects a negative value
|
||||
*/
|
||||
inline void setNearPlaneZ(float z) {
|
||||
debugAssert(z < 0);
|
||||
m_nearPlaneZ = z;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the GCamera space width of the viewport.
|
||||
Returns the camera space width of the viewport at the near plane.
|
||||
*/
|
||||
float getViewportWidth(
|
||||
const class Rect2D& viewport) const;
|
||||
float viewportWidth(const class Rect2D& viewport) const;
|
||||
|
||||
/**
|
||||
Returns the GCamera space height of the viewport.
|
||||
*/
|
||||
float getViewportHeight(
|
||||
const class Rect2D& viewport) const;
|
||||
|
||||
/**
|
||||
Read back a GCamera space z-value at pixel (x, y) from the depth buffer.
|
||||
double getZValue(
|
||||
double x,
|
||||
double y,
|
||||
const class Rect2D& viewport,
|
||||
double polygonOffset = 0) const;
|
||||
Returns the camera space height of the viewport at the near plane.
|
||||
*/
|
||||
float viewportHeight(const class Rect2D& viewport) const;
|
||||
|
||||
void setPosition(const Vector3& t);
|
||||
|
||||
/** Rotate the camera in place to look at the target. Does not
|
||||
persistently look at that location when the camera moves;
|
||||
i.e., if you move the camera and still want it to look at the
|
||||
old target, you must call lookAt again after moving the
|
||||
camera.)*/
|
||||
void lookAt(const Vector3& position, const Vector3& up = Vector3::unitY());
|
||||
|
||||
/**
|
||||
Returns the clipping planes of the frustum, in world space.
|
||||
The planes have normals facing <B>into</B> the view frustum.
|
||||
|
||||
The plane order is guaranteed to be:
|
||||
Near, Right, Left, Top, Bottom, [Far]
|
||||
|
||||
If the far plane is at infinity, the resulting array will have
|
||||
5 planes, otherwise there will be 6.
|
||||
|
||||
The viewport is used only to determine the aspect ratio of the screen; the
|
||||
absolute dimensions and xy values don't matter.
|
||||
/**
|
||||
Returns the clipping planes of the frustum, in world space.
|
||||
The planes have normals facing <B>into</B> the view frustum.
|
||||
|
||||
The plane order is guaranteed to be:
|
||||
Near, Right, Left, Top, Bottom, [Far]
|
||||
|
||||
If the far plane is at infinity, the resulting array will have
|
||||
5 planes, otherwise there will be 6.
|
||||
|
||||
The viewport is used only to determine the aspect ratio of the screen; the
|
||||
absolute dimensions and xy values don't matter.
|
||||
*/
|
||||
void getClipPlanes(
|
||||
const Rect2D& viewport,
|
||||
Array<Plane>& outClip) const;
|
||||
void getClipPlanes
|
||||
(
|
||||
const Rect2D& viewport,
|
||||
Array<Plane>& outClip) const;
|
||||
|
||||
/**
|
||||
Returns the world space view frustum, which is a truncated pyramid describing
|
||||
the volume of space seen by this camera.
|
||||
/**
|
||||
Returns the world space view frustum, which is a truncated pyramid describing
|
||||
the volume of space seen by this camera.
|
||||
*/
|
||||
void getFrustum(const Rect2D& viewport, GCamera::Frustum& f) const;
|
||||
|
||||
GCamera::Frustum frustum(const Rect2D& viewport) const;
|
||||
void frustum(const Rect2D& viewport, GCamera::Frustum& f) const;
|
||||
|
||||
GCamera::Frustum frustum(const Rect2D& viewport) const;
|
||||
|
||||
/** Read and Write camera parameters */
|
||||
void serialize(class BinaryOutput& bo) const;
|
||||
void deserialize(class BinaryInput& bi);
|
||||
|
||||
};
|
||||
|
||||
} // namespace G3D
|
||||
|
|
|
|||
607
dep/include/g3dlite/G3D/GImage.h
Normal file
607
dep/include/g3dlite/G3D/GImage.h
Normal file
|
|
@ -0,0 +1,607 @@
|
|||
/**
|
||||
\file GImage.h
|
||||
|
||||
See G3D::GImage for details.
|
||||
|
||||
@cite JPEG compress/decompressor is the <A HREF="http://www.ijg.org/files/">IJG library</A>, used in accordance with their license.
|
||||
@cite JPG code by John Chisholm, using the IJG Library
|
||||
@cite TGA code by Morgan McGuire
|
||||
@cite BMP code by John Chisholm, based on code by Edward "CGameProgrammer" Resnick <A HREF="mailto:cgp@gdnmail.net">mailto:cgp@gdnmail.net</A> at <A HREF="ftp://ftp.flipcode.com/cotd/LoadPicture.txt">ftp://ftp.flipcode.com/cotd/LoadPicture.txt</A>
|
||||
@cite PCX format described in the ZSOFT PCX manual http://www.nist.fss.ru/hr/doc/spec/pcx.htm#2
|
||||
@cite PNG compress/decompressor is the <A HREF="http://www.libpng.org/pub/png/libpng.html">libpng library</A>, used in accordance with their license.
|
||||
@cite PPM code by Morgan McGuire based on http://netpbm.sourceforge.net/doc/ppm.html
|
||||
|
||||
\maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
\created 2002-05-27
|
||||
\edited 2010-01-04
|
||||
|
||||
Copyright 2000-2010, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_GImage_h
|
||||
#define G3D_GImage_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include <string>
|
||||
#include "G3D/Array.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/stringutils.h"
|
||||
#include "G3D/Color1uint8.h"
|
||||
#include "G3D/Color3uint8.h"
|
||||
#include "G3D/Color4uint8.h"
|
||||
#include "G3D/MemoryManager.h"
|
||||
#include "G3D/BumpMapPreprocess.h"
|
||||
|
||||
namespace G3D {
|
||||
class BinaryInput;
|
||||
class BinaryOutput;
|
||||
|
||||
|
||||
/**
|
||||
Interface to image compression & file formats.
|
||||
|
||||
Supported formats (decode and encode): Color JPEG, PNG,
|
||||
(Uncompressed)TGA 24, (Uncompressed)TGA 32, BMP 1, BMP 4, BMP 8, BMP
|
||||
24, PPM (P6), and PPM ASCII (P1, P2, P3), which includes PPM, PGM,
|
||||
and PBM. 8-bit paletted PCX, 24-bit PCX, and ICO are supported for
|
||||
decoding only.
|
||||
|
||||
Sample usage:
|
||||
|
||||
\verbatim
|
||||
// Loading from disk:
|
||||
G3D::GImage im1("test.jpg");
|
||||
|
||||
// Loading from memory:
|
||||
G3D::GImage im2(data, length);
|
||||
|
||||
// im.pixel is a pointer to RGB color data. If you want
|
||||
// an alpha channel, call RGBtoRGBA or RGBtoARGB for
|
||||
// conversion.
|
||||
|
||||
// Saving to memory:
|
||||
G3D::GImage im3(width, height);
|
||||
// (Set the pixels of im3...)
|
||||
uint8* data2;
|
||||
int len2;
|
||||
im3.encode(G3D::GImage::JPEG, data2, len2);
|
||||
|
||||
// Saving to disk
|
||||
im3.save("out.jpg");
|
||||
\endverbatim
|
||||
|
||||
The free Image Magick Magick Wand API
|
||||
(http://www.imagemagick.org/www/api/magick_wand.html) provides a more powerful
|
||||
API for image manipulation and wider set of image load/save formats. It is
|
||||
recommended over GImage (we don't include it directly in G3D because their license
|
||||
is more restrictive than the BSD one).
|
||||
|
||||
*/
|
||||
class GImage {
|
||||
private:
|
||||
|
||||
/** Used exclusively for allocating m_byte; this may be an
|
||||
implementation that allocates directly on a GPU.*/
|
||||
MemoryManager::Ref m_memMan;
|
||||
uint8* m_byte;
|
||||
|
||||
int m_channels;
|
||||
int m_width;
|
||||
int m_height;
|
||||
|
||||
public:
|
||||
|
||||
class Error {
|
||||
public:
|
||||
Error(
|
||||
const std::string& reason,
|
||||
const std::string& filename = "") :
|
||||
reason(reason), filename(filename) {}
|
||||
|
||||
std::string reason;
|
||||
std::string filename;
|
||||
};
|
||||
|
||||
/** PGM, PPM, and PBM all come in two versions and are classified as PPM_* files */
|
||||
enum Format {JPEG, BMP, TGA, PCX, ICO, PNG,
|
||||
PPM_BINARY, PGM_BINARY = PPM_BINARY,
|
||||
PPM_ASCII, PGM_ASCII = PPM_ASCII,
|
||||
AUTODETECT, UNKNOWN};
|
||||
|
||||
|
||||
/**
|
||||
The number of channels; either 3 (RGB) or 4 (RGBA)
|
||||
*/
|
||||
inline int channels() const {
|
||||
return m_channels;
|
||||
}
|
||||
|
||||
inline int width() const {
|
||||
return m_width;
|
||||
}
|
||||
|
||||
inline int height() const {
|
||||
return m_height;
|
||||
}
|
||||
|
||||
inline const uint8* byte() const {
|
||||
return m_byte;
|
||||
}
|
||||
|
||||
/** Returns a pointer to the underlying data, which is stored
|
||||
in row-major order without row padding.
|
||||
e.g., <code>uint8* ptr = image.rawData<uint8>();
|
||||
*/
|
||||
template<typename Type>
|
||||
inline const Type* rawData() const {
|
||||
return (Type*)m_byte;
|
||||
}
|
||||
|
||||
/** \copybrief GImage::rawData() const */
|
||||
template<typename Type>
|
||||
inline Type* rawData() {
|
||||
return (Type*)m_byte;
|
||||
}
|
||||
|
||||
inline const Color1uint8* pixel1() const {
|
||||
debugAssertM(m_channels == 1, format("Tried to call GImage::pixel1 on an image with %d channels", m_channels));
|
||||
return (Color1uint8*)m_byte;
|
||||
}
|
||||
|
||||
inline Color1uint8* pixel1() {
|
||||
debugAssertM(m_channels == 1, format("Tried to call GImage::pixel1 on an image with %d channels", m_channels));
|
||||
return (Color1uint8*)m_byte;
|
||||
}
|
||||
|
||||
/** Returns a pointer to the upper left pixel
|
||||
as Color4uint8.
|
||||
*/
|
||||
inline const Color4uint8* pixel4() const {
|
||||
debugAssertM(m_channels == 4, format("Tried to call GImage::pixel4 on an image with %d channels", m_channels));
|
||||
return (Color4uint8*)m_byte;
|
||||
}
|
||||
|
||||
inline Color4uint8* pixel4() {
|
||||
debugAssert(m_channels == 4);
|
||||
return (Color4uint8*)m_byte;
|
||||
}
|
||||
|
||||
/** Returns a pointer to the upper left pixel
|
||||
as Color3uint8.
|
||||
*/
|
||||
inline const Color3uint8* pixel3() const {
|
||||
debugAssertM(m_channels == 3, format("Tried to call GImage::pixel3 on an image with %d channels", m_channels));
|
||||
return (Color3uint8*)m_byte;
|
||||
}
|
||||
|
||||
inline Color3uint8* pixel3() {
|
||||
debugAssert(m_channels == 3);
|
||||
return (Color3uint8*)m_byte;
|
||||
}
|
||||
|
||||
/** Returns the pixel at (x, y), where (0,0) is the upper left. */
|
||||
inline const Color1uint8& pixel1(int x, int y) const {
|
||||
debugAssert(x >= 0 && x < m_width);
|
||||
debugAssert(y >= 0 && y < m_height);
|
||||
return pixel1()[x + y * m_width];
|
||||
}
|
||||
|
||||
/** Returns the pixel at (x, y), where (0,0) is the upper left. */
|
||||
inline Color1uint8& pixel1(int x, int y) {
|
||||
debugAssert(x >= 0 && x < m_width);
|
||||
debugAssert(y >= 0 && y < m_height);
|
||||
return pixel1()[x + y * m_width];
|
||||
}
|
||||
|
||||
/** Returns the pixel at (x, y), where (0,0) is the upper left. */
|
||||
inline const Color3uint8& pixel3(int x, int y) const {
|
||||
debugAssert(x >= 0 && x < m_width);
|
||||
debugAssert(y >= 0 && y < m_height);
|
||||
return pixel3()[x + y * m_width];
|
||||
}
|
||||
|
||||
inline Color3uint8& pixel3(int x, int y) {
|
||||
debugAssert(x >= 0 && x < m_width);
|
||||
debugAssert(y >= 0 && y < m_height);
|
||||
return pixel3()[x + y * m_width];
|
||||
}
|
||||
|
||||
/** Returns the pixel at (x, y), where (0,0) is the upper left. */
|
||||
inline const Color4uint8& pixel4(int x, int y) const {
|
||||
debugAssert(x >= 0 && x < m_width);
|
||||
debugAssert(y >= 0 && y < m_height);
|
||||
return pixel4()[x + y * m_width];
|
||||
}
|
||||
|
||||
inline Color4uint8& pixel4(int x, int y) {
|
||||
debugAssert(x >= 0 && x < m_width);
|
||||
debugAssert(y >= 0 && y < m_height);
|
||||
return pixel4()[x + y * m_width];
|
||||
}
|
||||
|
||||
inline uint8* byte() {
|
||||
return m_byte;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void encodeBMP(
|
||||
BinaryOutput& out) const;
|
||||
|
||||
/**
|
||||
The TGA file will be either 24- or 32-bit depending
|
||||
on the number of channels.
|
||||
*/
|
||||
void encodeTGA(
|
||||
BinaryOutput& out) const;
|
||||
|
||||
/**
|
||||
Converts this image into a JPEG
|
||||
*/
|
||||
void encodeJPEG(
|
||||
BinaryOutput& out) const;
|
||||
|
||||
/**
|
||||
Converts this image into a JPEG
|
||||
*/
|
||||
void encodePNG(
|
||||
BinaryOutput& out) const;
|
||||
|
||||
void encodePPM(
|
||||
BinaryOutput& out) const;
|
||||
|
||||
void encodePPMASCII(
|
||||
BinaryOutput& out) const;
|
||||
|
||||
void decodeTGA(
|
||||
BinaryInput& input);
|
||||
|
||||
void decodeBMP(
|
||||
BinaryInput& input);
|
||||
|
||||
void decodeJPEG(
|
||||
BinaryInput& input);
|
||||
|
||||
void decodePCX(
|
||||
BinaryInput& input);
|
||||
|
||||
void decodeICO(
|
||||
BinaryInput& input);
|
||||
|
||||
void decodePNG(
|
||||
BinaryInput& input);
|
||||
|
||||
void decodePPM(
|
||||
BinaryInput& input);
|
||||
|
||||
void decodePPMASCII(
|
||||
BinaryInput& input);
|
||||
|
||||
/**
|
||||
Given [maybe] a filename, memory buffer, and [maybe] a format,
|
||||
returns the most likely format of this file.
|
||||
*/
|
||||
static Format resolveFormat(
|
||||
const std::string& filename,
|
||||
const uint8* data,
|
||||
int dataLen,
|
||||
Format maybeFormat);
|
||||
|
||||
void _copy(
|
||||
const GImage& other);
|
||||
|
||||
public:
|
||||
|
||||
/** Predicts the image file format of \a filename */
|
||||
static Format resolveFormat(const std::string& filename);
|
||||
|
||||
void flipHorizontal();
|
||||
void flipVertical();
|
||||
void rotate90CW(int numTimes = 1);
|
||||
|
||||
/**
|
||||
Create an empty image of the given size.
|
||||
\sa load()
|
||||
*/
|
||||
GImage(
|
||||
int width = 0,
|
||||
int height = 0,
|
||||
int channels = 3,
|
||||
const MemoryManager::Ref& m = MemoryManager::create());
|
||||
|
||||
/**
|
||||
Load an encoded image from disk and decode it.
|
||||
Throws GImage::Error if something goes wrong.
|
||||
*/
|
||||
GImage(
|
||||
const std::string& filename,
|
||||
Format format = AUTODETECT,
|
||||
const MemoryManager::Ref& m = MemoryManager::create());
|
||||
|
||||
/**
|
||||
Decodes an image stored in a buffer.
|
||||
*/
|
||||
GImage(
|
||||
const unsigned char*data,
|
||||
int length,
|
||||
Format format = AUTODETECT,
|
||||
const MemoryManager::Ref& m = MemoryManager::create());
|
||||
|
||||
GImage(
|
||||
const GImage& other,
|
||||
const MemoryManager::Ref& m = MemoryManager::create());
|
||||
|
||||
GImage& operator=(const GImage& other);
|
||||
|
||||
/**
|
||||
Returns a new GImage that has 4 channels. RGB is
|
||||
taken from this GImage and the alpha from the red
|
||||
channel of the supplied image. The new GImage is passed
|
||||
as a reference parameter for speed.
|
||||
*/
|
||||
void insertRedAsAlpha(const GImage& alpha, GImage& output) const;
|
||||
|
||||
/**
|
||||
Returns a new GImage with 3 channels, removing
|
||||
the alpha channel if there is one. The new GImage
|
||||
is passed as a reference parameter for speed.
|
||||
*/
|
||||
void stripAlpha(GImage& output) const;
|
||||
|
||||
/**
|
||||
Loads an image from disk (clearing the old one first),
|
||||
using the existing memory manager.
|
||||
*/
|
||||
void load(
|
||||
const std::string& filename,
|
||||
Format format = AUTODETECT);
|
||||
|
||||
/**
|
||||
Frees memory and resets to a 0x0 image.
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/**
|
||||
Deallocates the pixels.
|
||||
*/
|
||||
virtual ~GImage();
|
||||
|
||||
/**
|
||||
Resizes the internal buffer to (\a width x \a height) with the
|
||||
number of \a channels specified.
|
||||
|
||||
\param zero If true, all data is set to 0 (black).
|
||||
*/
|
||||
void resize(int width, int height, int channels, bool zero = true);
|
||||
|
||||
/**
|
||||
Copies src sub-image data into dest at a certain offset.
|
||||
The dest variable must already contain an image that is large
|
||||
enough to contain the src sub-image at the specified offset.
|
||||
Returns true on success and false if the src sub-image cannot
|
||||
completely fit within dest at the specified offset. Both
|
||||
src and dest must have the same number of channels.
|
||||
*/
|
||||
static bool pasteSubImage(
|
||||
GImage& dest,
|
||||
const GImage& src,
|
||||
int destX,
|
||||
int destY,
|
||||
int srcX,
|
||||
int srcY,
|
||||
int srcWidth,
|
||||
int srcHeight);
|
||||
|
||||
/**
|
||||
creates dest from src sub-image data.
|
||||
Returns true on success and false if the src sub-image
|
||||
is not within src.
|
||||
*/
|
||||
static bool copySubImage(GImage & dest, const GImage & src,
|
||||
int srcX, int srcY, int srcWidth, int srcHeight);
|
||||
|
||||
void convertToRGBA();
|
||||
|
||||
void convertToRGB();
|
||||
|
||||
/** Averages color channels if they exist */
|
||||
void convertToL8();
|
||||
|
||||
/**
|
||||
Returns true if format is supported. Format
|
||||
should be an extension string (e.g. "BMP").
|
||||
*/
|
||||
static bool supportedFormat(
|
||||
const std::string& format);
|
||||
|
||||
/**
|
||||
Converts a string to an enum, returns UNKNOWN if not recognized.
|
||||
*/
|
||||
static Format stringToFormat(
|
||||
const std::string& format);
|
||||
|
||||
/**
|
||||
Encode and save to disk.
|
||||
*/
|
||||
void save(
|
||||
const std::string& filename,
|
||||
Format format = AUTODETECT) const;
|
||||
|
||||
/**
|
||||
The caller must delete the returned buffer.
|
||||
TODO: provide a memory manager
|
||||
*/
|
||||
void encode(
|
||||
Format format,
|
||||
uint8*& outData,
|
||||
int& outLength) const;
|
||||
|
||||
/**
|
||||
Does not commit the BinaryOutput when done.
|
||||
*/
|
||||
void encode(
|
||||
Format format,
|
||||
BinaryOutput& out) const;
|
||||
|
||||
/**
|
||||
Decodes the buffer into this image.
|
||||
@param format Must be the correct format.
|
||||
*/
|
||||
void decode(
|
||||
BinaryInput& input,
|
||||
Format format);
|
||||
|
||||
/** Returns the size of this object in bytes */
|
||||
int sizeInMemory() const;
|
||||
|
||||
/** Ok for in == out */
|
||||
static void R8G8B8_to_Y8U8V8(int width, int height, const uint8* in, uint8* out);
|
||||
|
||||
/** Ok for in == out */
|
||||
static void Y8U8V8_to_R8G8B8(int width, int height, const uint8* in, uint8* out);
|
||||
|
||||
/**
|
||||
@param in RGB buffer of numPixels * 3 bytes
|
||||
@param out Buffer of numPixels * 4 bytes
|
||||
@param numPixels Number of RGB pixels to convert
|
||||
*/
|
||||
static void RGBtoRGBA(
|
||||
const uint8* in,
|
||||
uint8* out,
|
||||
int numPixels);
|
||||
|
||||
static void RGBtoARGB(
|
||||
const uint8* in,
|
||||
uint8* out,
|
||||
int numPixels);
|
||||
|
||||
static void LtoRGB
|
||||
(const uint8* in,
|
||||
uint8* out,
|
||||
int numPixels);
|
||||
|
||||
static void LtoRGBA
|
||||
(const uint8* in,
|
||||
uint8* out,
|
||||
int numPixels);
|
||||
|
||||
/** Safe for in == out */
|
||||
static void RGBtoBGR(
|
||||
const uint8* in,
|
||||
uint8* out,
|
||||
int numPixels);
|
||||
|
||||
/**
|
||||
Win32 32-bit HDC format.
|
||||
*/
|
||||
static void RGBtoBGRA(
|
||||
const uint8* in,
|
||||
uint8* out,
|
||||
int numPixels);
|
||||
|
||||
static void RGBAtoRGB(
|
||||
const uint8* in,
|
||||
uint8* out,
|
||||
int numPixels);
|
||||
/**
|
||||
Uses the red channel of the second image as an alpha channel.
|
||||
*/
|
||||
static void RGBxRGBtoRGBA(
|
||||
const uint8* colorRGB,
|
||||
const uint8* alphaRGB,
|
||||
uint8* out,
|
||||
int numPixels);
|
||||
|
||||
/**
|
||||
Flips the image along the vertical axis.
|
||||
Safe for in == out.
|
||||
*/
|
||||
static void flipRGBVertical(
|
||||
const uint8* in,
|
||||
uint8* out,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
static void flipRGBAVertical(
|
||||
const uint8* in,
|
||||
uint8* out,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
/**
|
||||
Given a tangent space bump map, computes a new image where the
|
||||
RGB channels are a tangent space normal map and the alpha channel
|
||||
is the original bump map. Assumes the input image is tileable.
|
||||
|
||||
In the resulting image, x = red = tangent, y = green = binormal, and z = blue = normal.
|
||||
|
||||
Particularly useful as part of the idiom:
|
||||
<PRE>
|
||||
GImage normal;
|
||||
computeNormalMap(GImage(filename), normal);
|
||||
return Texture::fromGImage(filename, normal);
|
||||
</PRE>
|
||||
|
||||
*/
|
||||
static void computeNormalMap(
|
||||
const class GImage& bump,
|
||||
class GImage& normal,
|
||||
const BumpMapPreprocess& preprocess = BumpMapPreprocess());
|
||||
|
||||
static void computeNormalMap
|
||||
(int width,
|
||||
int height,
|
||||
int channels,
|
||||
const uint8* src,
|
||||
GImage& normal,
|
||||
const BumpMapPreprocess& preprocess = BumpMapPreprocess());
|
||||
|
||||
/**
|
||||
Bayer demosaicing using the filter proposed in
|
||||
|
||||
HIGH-QUALITY LINEAR INTERPOLATION FOR DEMOSAICING OF BAYER-PATTERNED COLOR IMAGES
|
||||
Henrique S. Malvar, Li-wei He, and Ross Cutler
|
||||
|
||||
The filter wraps at the image boundaries.
|
||||
|
||||
Assumes in != out.
|
||||
*/
|
||||
static void BAYER_G8B8_R8G8_to_R8G8B8_MHC(int w, int h, const uint8* in, uint8* _out);
|
||||
static void BAYER_G8R8_B8G8_to_R8G8B8_MHC(int w, int h, const uint8* in, uint8* _out);
|
||||
static void BAYER_R8G8_G8B8_to_R8G8B8_MHC(int w, int h, const uint8* in, uint8* _out);
|
||||
static void BAYER_B8G8_G8R8_to_R8G8B8_MHC(int w, int h, const uint8* in, uint8* _out);
|
||||
|
||||
/** Fast conversion; the output has 1/2 the size of the input in each direction. Assumes in != out.
|
||||
See G3D::BAYER_G8B8_R8G8_to_R8G8B8_MHC for a much better result. */
|
||||
static void BAYER_G8B8_R8G8_to_Quarter_R8G8B8
|
||||
(int inWidth,
|
||||
int inHeight,
|
||||
const uint8* in,
|
||||
uint8* out);
|
||||
|
||||
/** Attempt to undo fast conversion of G3D::BAYER_G8B8_R8G8_to_Quarter_R8G8B8;
|
||||
the green channel will lose data. Assumes in != out
|
||||
The input should have size 3 * inWidth * inHeight. The output should have size
|
||||
2 * inWidth * 2 * inHeight.
|
||||
*/
|
||||
static void Quarter_R8G8B8_to_BAYER_G8B8_R8G8
|
||||
(int inWidth,
|
||||
int inHeight,
|
||||
const uint8* in,
|
||||
uint8* out);
|
||||
|
||||
/** Overwrites every pixel with one of the two colors in a checkerboard pattern.
|
||||
The fields used from the two colors depend on the current number of channels in @a im.
|
||||
*/
|
||||
static void makeCheckerboard
|
||||
(GImage& im,
|
||||
int checkerSize = 1,
|
||||
const Color4uint8& color1 = Color4uint8(255,255,255,255),
|
||||
const Color4uint8& color2 = Color4uint8(0,0,0,255));
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
106
dep/include/g3dlite/G3D/GLight.h
Normal file
106
dep/include/g3dlite/G3D/GLight.h
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
/**
|
||||
@file GLight.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2003-11-12
|
||||
@edited 2009-11-08
|
||||
*/
|
||||
|
||||
#ifndef G3D_GLight_h
|
||||
#define G3D_GLight_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Vector4.h"
|
||||
#include "G3D/Vector3.h"
|
||||
#include "G3D/Color4.h"
|
||||
|
||||
namespace G3D {
|
||||
class Any;
|
||||
|
||||
/**
|
||||
A light representation that closely follows the OpenGL light format.
|
||||
*/
|
||||
class GLight {
|
||||
public:
|
||||
/** World space position (for a directional light, w = 0 */
|
||||
Vector4 position;
|
||||
|
||||
/** For a spot or directional light, this is the "right vector" that will be used when constructing
|
||||
a reference frame(). */
|
||||
Vector3 rightDirection;
|
||||
|
||||
/** Direction in which the light faces, if a spot light. This is the "look vector" of the light source. */
|
||||
Vector3 spotDirection;
|
||||
|
||||
/** In <B>degrees</B>. 180 = no cutoff (point/dir). Values less than 90 = spot light */
|
||||
float spotCutoff;
|
||||
|
||||
/** If true, G3D::SuperShader will render a cone of light large
|
||||
enough to encompass the entire square that bounds the cutoff
|
||||
angle. This produces a square prism instead of a cone of light
|
||||
when used with a G3D::ShadowMap. for an unshadowed light this
|
||||
has no effect.*/
|
||||
bool spotSquare;
|
||||
|
||||
/** Constant, linear, quadratic */
|
||||
float attenuation[3];
|
||||
|
||||
/** May be outside the range [0, 1] */
|
||||
Color3 color;
|
||||
|
||||
/** If false, this light is ignored */
|
||||
bool enabled;
|
||||
|
||||
/** If false, this light does not create specular highlights
|
||||
(useful when using negative lights). */
|
||||
bool specular;
|
||||
|
||||
/** If false, this light does not create diffuse illumination
|
||||
(useful when rendering a specular-only pass). */
|
||||
bool diffuse;
|
||||
|
||||
GLight();
|
||||
|
||||
/** Accepted forms:
|
||||
- GLight::directional( vector3, color3, [bool, [bool]])
|
||||
- GLight::spot(vector3, vector3, #, color3, [#, [#, [#, [#, [bool, [bool]]]])
|
||||
- GLight::point(vector3, color3, [#, [#, [#, [#, [bool, [bool]]]])
|
||||
- GLight { [all fields] }
|
||||
*/
|
||||
GLight(const Any& any);
|
||||
|
||||
/** Converts the Color3 to an Any. */
|
||||
operator Any() const;
|
||||
|
||||
/** @param toLight will be normalized */
|
||||
static GLight directional(const Vector3& toLight, const Color3& color, bool specular = true, bool diffuse = true);
|
||||
|
||||
static GLight point(const Vector3& pos, const Color3& color, float constAtt = 1, float linAtt = 0, float quadAtt = 0.5f, bool specular = true, bool diffuse = true);
|
||||
|
||||
/** @param pointDirection Will be normalized. Points in the
|
||||
direction that light propagates.
|
||||
|
||||
@param cutOffAngleDegrees Must be on the range [0, 90]. This
|
||||
is the angle from the point direction to the edge of the light
|
||||
cone. I.e., a value of 45 produces a light with a 90-degree
|
||||
cone of view.
|
||||
*/
|
||||
static GLight spot(const Vector3& pos, const Vector3& pointDirection, float cutOffAngleDegrees,
|
||||
const Color3& color, float constAtt = 1, float linAtt = 0, float quadAtt = 0,
|
||||
bool specular = true, bool diffuse = true);
|
||||
|
||||
/** Returns the sphere within which this light has some noticable effect. May be infinite.
|
||||
@param cutoff The value at which the light intensity is considered negligible. */
|
||||
class Sphere effectSphere(float cutoff = 30.0f / 255) const;
|
||||
|
||||
/** Computes a reference frame (e.g., for use with G3D::ShadowMap */
|
||||
class CoordinateFrame frame() const;
|
||||
|
||||
bool operator==(const GLight& other) const;
|
||||
bool operator!=(const GLight& other) const;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
#endif
|
||||
|
||||
123
dep/include/g3dlite/G3D/GMutex.h
Normal file
123
dep/include/g3dlite/G3D/GMutex.h
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
/**
|
||||
@file GMutex.h
|
||||
|
||||
@created 2005-09-22
|
||||
@edited 2009-03-25
|
||||
*/
|
||||
|
||||
#ifndef G3D_GMutex_h
|
||||
#define G3D_GMutex_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/AtomicInt32.h"
|
||||
#include "G3D/debugAssert.h"
|
||||
#include <string>
|
||||
|
||||
#ifndef G3D_WIN32
|
||||
# include <pthread.h>
|
||||
# include <signal.h>
|
||||
#endif
|
||||
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
\brief A mutual exclusion lock that busy-waits when locking.
|
||||
|
||||
On a machine with one (significant) thread per processor core,
|
||||
a spinlock may be substantially faster than a mutex.
|
||||
|
||||
\sa G3D::GThread, G3D::GMutex, G3D::AtomicInt32
|
||||
*/
|
||||
class Spinlock {
|
||||
private:
|
||||
|
||||
AtomicInt32 x;
|
||||
|
||||
public:
|
||||
|
||||
inline Spinlock() : x(0) {}
|
||||
|
||||
/** Busy waits until the lock is unlocked, then locks it
|
||||
exclusively. Returns true if the lock succeeded on the first
|
||||
try (indicating no contention). */
|
||||
inline bool lock() {
|
||||
bool first = true;
|
||||
while (x.compareAndSet(0, 1) == 1) {
|
||||
first = false;
|
||||
# ifdef G3D_WIN32
|
||||
Sleep(0);
|
||||
# else
|
||||
usleep(0);
|
||||
# endif
|
||||
}
|
||||
return first;
|
||||
}
|
||||
|
||||
inline void unlock() {
|
||||
x.compareAndSet(1, 0);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
\brief Mutual exclusion lock used for synchronization.
|
||||
|
||||
@sa G3D::GThread, G3D::AtomicInt32, G3D::Spinlock
|
||||
*/
|
||||
class GMutex {
|
||||
private:
|
||||
# ifdef G3D_WIN32
|
||||
CRITICAL_SECTION m_handle;
|
||||
# else
|
||||
pthread_mutex_t m_handle;
|
||||
pthread_mutexattr_t m_attr;
|
||||
# endif
|
||||
|
||||
// Not implemented on purpose, don't use
|
||||
GMutex(const GMutex &mlock);
|
||||
GMutex &operator=(const GMutex &);
|
||||
bool operator==(const GMutex&);
|
||||
|
||||
public:
|
||||
GMutex();
|
||||
~GMutex();
|
||||
|
||||
/** Locks the mutex or blocks until available. */
|
||||
void lock();
|
||||
|
||||
/** Locks the mutex if it not already locked.
|
||||
Returns true if lock successful, false otherwise. */
|
||||
bool tryLock();
|
||||
|
||||
/** Unlocks the mutex. */
|
||||
void unlock();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Automatically locks while in scope.
|
||||
*/
|
||||
class GMutexLock {
|
||||
private:
|
||||
GMutex* m;
|
||||
|
||||
// Not implemented on purpose, don't use
|
||||
GMutexLock(const GMutexLock &mlock);
|
||||
GMutexLock &operator=(const GMutexLock &);
|
||||
bool operator==(const GMutexLock&);
|
||||
|
||||
public:
|
||||
GMutexLock(GMutex* mutex) {
|
||||
m = mutex;
|
||||
m->lock();
|
||||
}
|
||||
|
||||
~GMutexLock() {
|
||||
m->unlock();
|
||||
}
|
||||
};
|
||||
|
||||
} // G3D
|
||||
|
||||
#endif
|
||||
121
dep/include/g3dlite/G3D/GThread.h
Normal file
121
dep/include/g3dlite/G3D/GThread.h
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
/**
|
||||
@file GThread.h
|
||||
|
||||
@created 2005-09-22
|
||||
@edited 2007-01-31
|
||||
|
||||
*/
|
||||
|
||||
#ifndef G3D_GTHREAD_H
|
||||
#define G3D_GTHREAD_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/ReferenceCount.h"
|
||||
#include <string>
|
||||
|
||||
#ifndef G3D_WIN32
|
||||
# include <pthread.h>
|
||||
# include <signal.h>
|
||||
#endif
|
||||
|
||||
|
||||
namespace G3D {
|
||||
|
||||
typedef ReferenceCountedPointer<class GThread> GThreadRef;
|
||||
|
||||
/**
|
||||
Platform independent thread implementation. You can either subclass and
|
||||
override GThread::threadMain or call the create method with a method.
|
||||
|
||||
Beware of reference counting and threads. If circular references exist between
|
||||
GThread subclasses then neither class will ever be deallocated. Also,
|
||||
dropping all pointers (and causing deallocation) of a GThread does NOT
|
||||
stop the underlying process.
|
||||
|
||||
@sa G3D::GMutex, G3D::Spinlock, G3D::AtomicInt32
|
||||
*/
|
||||
class GThread : public ReferenceCountedObject {
|
||||
private:
|
||||
// "Status" is a reserved work on FreeBSD
|
||||
enum GStatus {STATUS_CREATED, STATUS_STARTED, STATUS_RUNNING, STATUS_COMPLETED};
|
||||
|
||||
// Not implemented on purpose, don't use
|
||||
GThread(const GThread &);
|
||||
GThread& operator=(const GThread&);
|
||||
bool operator==(const GThread&);
|
||||
|
||||
#ifdef G3D_WIN32
|
||||
static DWORD WINAPI internalThreadProc(LPVOID param);
|
||||
#else
|
||||
static void* internalThreadProc(void* param);
|
||||
#endif //G3D_WIN32
|
||||
|
||||
volatile GStatus m_status;
|
||||
|
||||
// Thread handle to hold HANDLE and pthread_t
|
||||
#ifdef G3D_WIN32
|
||||
HANDLE m_handle;
|
||||
HANDLE m_event;
|
||||
#else
|
||||
pthread_t m_handle;
|
||||
#endif //G3D_WIN32
|
||||
|
||||
std::string m_name;
|
||||
|
||||
protected:
|
||||
|
||||
/** Overriden by the thread implementor */
|
||||
virtual void threadMain() = 0;
|
||||
|
||||
public:
|
||||
typedef ReferenceCountedPointer<class GThread> Ref;
|
||||
enum SpawnBehavior {USE_NEW_THREAD, USE_CURRENT_THREAD};
|
||||
|
||||
GThread(const std::string& name);
|
||||
|
||||
virtual ~GThread();
|
||||
|
||||
/** Constructs a basic GThread without requiring a subclass.
|
||||
|
||||
@param proc The global or static function for the threadMain() */
|
||||
static GThreadRef create(const std::string& name, void (*proc)(void*), void* param = NULL);
|
||||
|
||||
/** Starts the thread and executes threadMain(). Returns false if
|
||||
the thread failed to start (either because it was already started
|
||||
or because the OS refused).
|
||||
|
||||
@param behavior If USE_CURRENT_THREAD, rather than spawning a new thread, this routine
|
||||
runs threadMain on the current thread.
|
||||
*/
|
||||
bool start(SpawnBehavior behavior = USE_NEW_THREAD);
|
||||
|
||||
/** Terminates the thread without notifying or
|
||||
waiting for a cancelation point. */
|
||||
void terminate();
|
||||
|
||||
/**
|
||||
Returns true if threadMain is currently executing. This will
|
||||
only be set when the thread is actually running and might not
|
||||
be set when start() returns. */
|
||||
bool running() const;
|
||||
|
||||
/** True after start() has been called, even through the thread
|
||||
may have already completed(), or be currently running().*/
|
||||
bool started() const;
|
||||
|
||||
/** Returns true if the thread has exited. */
|
||||
bool completed() const;
|
||||
|
||||
/** Waits for the thread to finish executing. */
|
||||
void waitForCompletion();
|
||||
|
||||
/** Returns thread name */
|
||||
inline const std::string& name() {
|
||||
return m_name;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace G3D
|
||||
|
||||
#endif //G3D_GTHREAD_H
|
||||
69
dep/include/g3dlite/G3D/GUniqueID.h
Normal file
69
dep/include/g3dlite/G3D/GUniqueID.h
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
/**
|
||||
@file GUniqueID.h
|
||||
@author Morgan McGuire, http://graphics.cs.williams.edu
|
||||
*/
|
||||
#ifndef G3D_GUNIQUEID_H
|
||||
#define G3D_GUNIQUEID_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/Table.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/** Globally unique identifiers. The probability of two different
|
||||
programs generating the same value from UniqueID::create is
|
||||
vanishingly small.
|
||||
|
||||
UniqueIDs optionally contain a 10-bit application specific tag
|
||||
that distinguishes their type.
|
||||
*/
|
||||
class GUniqueID {
|
||||
private:
|
||||
|
||||
uint64 id;
|
||||
|
||||
public:
|
||||
|
||||
GUniqueID() : id(0) {}
|
||||
|
||||
bool uninitialized() const {
|
||||
return id == 0;
|
||||
}
|
||||
|
||||
uint16 tag() const {
|
||||
return id >> 54;
|
||||
}
|
||||
|
||||
operator uint64() const {
|
||||
return id;
|
||||
}
|
||||
|
||||
bool operator==(const GUniqueID& other) const {
|
||||
return id == other.id;
|
||||
}
|
||||
|
||||
bool operator!=(const GUniqueID& other) const {
|
||||
return id != other.id;
|
||||
}
|
||||
|
||||
void serialize(class BinaryOutput& b) const;
|
||||
|
||||
void deserialize(class BinaryInput& b);
|
||||
|
||||
void serialize(class TextOutput& t) const;
|
||||
|
||||
void deserialize(class TextInput& t);
|
||||
|
||||
/** Create a new ID */
|
||||
static GUniqueID create(uint16 tag = 0);
|
||||
};
|
||||
|
||||
} // G3D
|
||||
|
||||
/** For Table and Set */
|
||||
template<> struct HashTrait<class G3D::GUniqueID> {
|
||||
static size_t hashCode(G3D::GUniqueID id) { return (size_t)(G3D::uint64)id; }
|
||||
};
|
||||
|
||||
#endif
|
||||
92
dep/include/g3dlite/G3D/HashTrait.h
Normal file
92
dep/include/g3dlite/G3D/HashTrait.h
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
/**
|
||||
@file HashTrait.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
@created 2008-10-01
|
||||
@edited 2009-11-01
|
||||
|
||||
Copyright 2000-2009, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_HashTrait_h
|
||||
#define G3D_HashTrait_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Crypto.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/uint128.h"
|
||||
|
||||
/** Must be specialized for custom types.
|
||||
@see G3D::Table for specialization requirements.
|
||||
*/
|
||||
template <typename T> struct HashTrait{};
|
||||
|
||||
template <typename T> struct HashTrait<T*> {
|
||||
static size_t hashCode(const void* k) { return reinterpret_cast<size_t>(k); }
|
||||
};
|
||||
|
||||
#if 0
|
||||
template <> struct HashTrait <int> {
|
||||
static size_t hashCode(int k) { return static_cast<size_t>(k); }
|
||||
};
|
||||
#endif
|
||||
|
||||
template <> struct HashTrait <G3D::int16> {
|
||||
static size_t hashCode(G3D::int16 k) { return static_cast<size_t>(k); }
|
||||
};
|
||||
|
||||
template <> struct HashTrait <G3D::uint16> {
|
||||
static size_t hashCode(G3D::uint16 k) { return static_cast<size_t>(k); }
|
||||
};
|
||||
|
||||
//template <> struct HashTrait <int> {
|
||||
// static size_t hashCode(int k) { return static_cast<size_t>(k); }
|
||||
//};
|
||||
|
||||
template <> struct HashTrait <G3D::int32> {
|
||||
static size_t hashCode(G3D::int32 k) { return static_cast<size_t>(k); }
|
||||
};
|
||||
|
||||
template <> struct HashTrait <G3D::uint32> {
|
||||
static size_t hashCode(G3D::uint32 k) { return static_cast<size_t>(k); }
|
||||
};
|
||||
|
||||
#if 0
|
||||
template <> struct HashTrait <long unsigned int> {
|
||||
static size_t hashCode(G3D::uint32 k) { return static_cast<size_t>(k); }
|
||||
};
|
||||
#endif
|
||||
|
||||
template <> struct HashTrait <G3D::int64> {
|
||||
static size_t hashCode(G3D::int64 k) { return static_cast<size_t>(k); }
|
||||
};
|
||||
|
||||
template <> struct HashTrait <G3D::uint64> {
|
||||
static size_t hashCode(G3D::uint64 k) { return static_cast<size_t>(k); }
|
||||
};
|
||||
|
||||
template <> struct HashTrait <std::string> {
|
||||
static size_t hashCode(const std::string& k) { return static_cast<size_t>(G3D::Crypto::crc32(k.c_str(), k.size())); }
|
||||
};
|
||||
|
||||
template <> struct HashTrait<G3D::uint128> {
|
||||
// Use the FNV-1 hash (http://isthe.com/chongo/tech/comp/fnv/#FNV-1).
|
||||
static size_t hashCode(G3D::uint128 key) {
|
||||
static const G3D::uint128 FNV_PRIME_128(1 << 24, 0x159);
|
||||
static const G3D::uint128 FNV_OFFSET_128(0xCF470AAC6CB293D2ULL, 0xF52F88BF32307F8FULL);
|
||||
|
||||
G3D::uint128 hash = FNV_OFFSET_128;
|
||||
G3D::uint128 mask(0, 0xFF);
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
hash *= FNV_PRIME_128;
|
||||
hash ^= (mask & key);
|
||||
key >>= 8;
|
||||
}
|
||||
|
||||
G3D::uint64 foldedHash = hash.hi ^ hash.lo;
|
||||
return static_cast<size_t>((foldedHash >> 32) ^ (foldedHash & 0xFFFFFFFF));
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
81
dep/include/g3dlite/G3D/Image1.h
Normal file
81
dep/include/g3dlite/G3D/Image1.h
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
/**
|
||||
@file Image1.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2007-01-31
|
||||
@edited 2007-01-31
|
||||
*/
|
||||
|
||||
|
||||
#ifndef G3D_IMAGE1_H
|
||||
#define G3D_IMAGE1_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Map2D.h"
|
||||
#include "G3D/Color1.h"
|
||||
#include "G3D/GImage.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
typedef ReferenceCountedPointer<class Image1> Image1Ref;
|
||||
|
||||
/**
|
||||
Luminance image with 32-bit floating point storage.
|
||||
|
||||
See also G3D::Image1uint8, G3D::GImage.
|
||||
*/
|
||||
class Image1 : public Map2D<Color1, Color1> {
|
||||
public:
|
||||
|
||||
typedef Image1 Type;
|
||||
typedef ReferenceCountedPointer<class Image1> Ref;
|
||||
typedef Color1 Storage;
|
||||
typedef Color1 Compute;
|
||||
|
||||
protected:
|
||||
|
||||
Image1(int w, int h, WrapMode wrap);
|
||||
|
||||
void copyGImage(const class GImage& im);
|
||||
void copyArray(const Color1* src, int w, int h);
|
||||
void copyArray(const Color3* src, int w, int h);
|
||||
void copyArray(const Color4* src, int w, int h);
|
||||
void copyArray(const Color1uint8* src, int w, int h);
|
||||
void copyArray(const Color3uint8* src, int w, int h);
|
||||
void copyArray(const Color4uint8* src, int w, int h);
|
||||
|
||||
public:
|
||||
|
||||
const class ImageFormat* format() const;
|
||||
|
||||
/** Creates an all-zero width x height image. */
|
||||
static Ref createEmpty(int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
/** Creates a 0 x 0 image. */
|
||||
static Ref createEmpty(WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
static Ref fromFile(const std::string& filename, WrapMode wrap = WrapMode::ERROR, GImage::Format fmt = GImage::AUTODETECT);
|
||||
|
||||
static Ref fromArray(const class Color1uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color3uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color4uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color1* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color3* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color4* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
static Ref fromImage1uint8(const ReferenceCountedPointer<class Image1uint8>& im);
|
||||
|
||||
static Ref fromGImage(const class GImage& im, WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
/** Loads from any of the file formats supported by G3D::GImage. If there is an alpha channel on the input,
|
||||
it is stripped. */
|
||||
void load(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT);
|
||||
|
||||
/** Saves in any of the formats supported by G3D::GImage. */
|
||||
void save(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT);
|
||||
};
|
||||
|
||||
} // G3D
|
||||
|
||||
#endif
|
||||
80
dep/include/g3dlite/G3D/Image1uint8.h
Normal file
80
dep/include/g3dlite/G3D/Image1uint8.h
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
/**
|
||||
@file Image1uint8.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2007-01-31
|
||||
@edited 2007-01-31
|
||||
*/
|
||||
|
||||
#ifndef G3D_IMAGE1UINT8_H
|
||||
#define G3D_IMAGE1UINT8_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Map2D.h"
|
||||
#include "G3D/Color1uint8.h"
|
||||
#include "G3D/Color1.h"
|
||||
#include "G3D/GImage.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
typedef ReferenceCountedPointer<class Image1uint8> Image1uint8Ref;
|
||||
|
||||
/**
|
||||
Compact storage for luminance 8-bit images.
|
||||
|
||||
See also G3D::Image3, G3D::GImage
|
||||
*/
|
||||
class Image1uint8 : public Map2D<Color1uint8, Color1> {
|
||||
public:
|
||||
|
||||
typedef Image1uint8 Type;
|
||||
typedef Image1uint8Ref Ref;
|
||||
|
||||
protected:
|
||||
|
||||
Image1uint8(int w, int h, WrapMode wrap);
|
||||
|
||||
void copyGImage(const class GImage& im);
|
||||
void copyArray(const Color1* src, int w, int h);
|
||||
void copyArray(const Color3* src, int w, int h);
|
||||
void copyArray(const Color4* src, int w, int h);
|
||||
void copyArray(const Color1uint8* src, int w, int h);
|
||||
void copyArray(const Color3uint8* src, int w, int h);
|
||||
void copyArray(const Color4uint8* src, int w, int h);
|
||||
|
||||
public:
|
||||
|
||||
const class ImageFormat* format() const;
|
||||
|
||||
/** Creates an all-zero width x height image. */
|
||||
static Ref createEmpty(int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
/** Creates a 0 x 0 image. */
|
||||
static Ref createEmpty(WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
static Ref fromFile(const std::string& filename, WrapMode wrap = WrapMode::ERROR, GImage::Format fmt = GImage::AUTODETECT);
|
||||
|
||||
static Ref fromGImage(const class GImage& im, WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
static Ref fromArray(const class Color1uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color3uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color4uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color1* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color3* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color4* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
static Ref fromImage1(const ReferenceCountedPointer<class Image1>& im);
|
||||
static Ref fromImage3uint8(const ReferenceCountedPointer<class Image3uint8>& im);
|
||||
|
||||
/** Loads from any of the file formats supported by G3D::GImage. If there is an alpha channel on the input,
|
||||
it is stripped. */
|
||||
void load(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT);
|
||||
|
||||
/** Saves in any of the formats supported by G3D::GImage. */
|
||||
void save(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT);
|
||||
};
|
||||
|
||||
} // G3D
|
||||
|
||||
#endif
|
||||
81
dep/include/g3dlite/G3D/Image3.h
Normal file
81
dep/include/g3dlite/G3D/Image3.h
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
/**
|
||||
@file Image3.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2007-01-31
|
||||
@edited 2007-01-31
|
||||
*/
|
||||
|
||||
|
||||
#ifndef G3D_IMAGE3_H
|
||||
#define G3D_IMAGE3_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Map2D.h"
|
||||
#include "G3D/Color3.h"
|
||||
#include "G3D/GImage.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
typedef ReferenceCountedPointer<class Image3> Image3Ref;
|
||||
|
||||
/**
|
||||
RGB image with 32-bit floating point storage for each channel.
|
||||
|
||||
See also G3D::Image3uint8, G3D::GImage.
|
||||
*/
|
||||
class Image3 : public Map2D<Color3, Color3> {
|
||||
public:
|
||||
|
||||
typedef Image3 Type;
|
||||
typedef ReferenceCountedPointer<class Image3> Ref;
|
||||
typedef Color3 Storage;
|
||||
typedef Color3 Compute;
|
||||
|
||||
protected:
|
||||
|
||||
Image3(int w, int h, WrapMode wrap);
|
||||
|
||||
void copyGImage(const class GImage& im);
|
||||
void copyArray(const Color1* src, int w, int h);
|
||||
void copyArray(const Color3* src, int w, int h);
|
||||
void copyArray(const Color4* src, int w, int h);
|
||||
void copyArray(const Color1uint8* src, int w, int h);
|
||||
void copyArray(const Color3uint8* src, int w, int h);
|
||||
void copyArray(const Color4uint8* src, int w, int h);
|
||||
|
||||
public:
|
||||
|
||||
const class ImageFormat* format() const;
|
||||
|
||||
/** Creates an all-zero width x height image. */
|
||||
static Ref createEmpty(int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
/** Creates a 0 x 0 image. */
|
||||
static Ref createEmpty(WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
static Ref fromFile(const std::string& filename, WrapMode wrap = WrapMode::ERROR, GImage::Format fmt = GImage::AUTODETECT);
|
||||
|
||||
static Ref fromArray(const class Color1uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color3uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color4uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color1* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color3* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color4* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
static Ref fromImage3uint8(const ReferenceCountedPointer<class Image3uint8>& im);
|
||||
|
||||
static Ref fromGImage(const class GImage& im, WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
/** Loads from any of the file formats supported by G3D::GImage. If there is an alpha channel on the input,
|
||||
it is stripped. */
|
||||
void load(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT);
|
||||
|
||||
/** Saves in any of the formats supported by G3D::GImage. */
|
||||
void save(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT);
|
||||
};
|
||||
|
||||
} // G3D
|
||||
|
||||
#endif
|
||||
85
dep/include/g3dlite/G3D/Image3uint8.h
Normal file
85
dep/include/g3dlite/G3D/Image3uint8.h
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
/**
|
||||
@file Image3uint8.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2007-01-31
|
||||
@edited 2007-01-31
|
||||
*/
|
||||
|
||||
#ifndef G3D_IMAGE3UINT8_H
|
||||
#define G3D_IMAGE3UINT8_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Map2D.h"
|
||||
#include "G3D/Color3uint8.h"
|
||||
#include "G3D/Color3.h"
|
||||
#include "G3D/GImage.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
typedef ReferenceCountedPointer<class Image3uint8> Image3uint8Ref;
|
||||
|
||||
/**
|
||||
Compact storage for RGB 8-bit per channel images.
|
||||
|
||||
See also G3D::Image3, G3D::GImage
|
||||
*/
|
||||
class Image3uint8 : public Map2D<Color3uint8, Color3> {
|
||||
public:
|
||||
|
||||
typedef Image3uint8 Type;
|
||||
typedef Image3uint8Ref Ref;
|
||||
|
||||
protected:
|
||||
|
||||
Image3uint8(int w, int h, WrapMode wrap);
|
||||
|
||||
void copyGImage(const class GImage& im);
|
||||
void copyArray(const Color1* src, int w, int h);
|
||||
void copyArray(const Color3* src, int w, int h);
|
||||
void copyArray(const Color4* src, int w, int h);
|
||||
void copyArray(const Color1uint8* src, int w, int h);
|
||||
void copyArray(const Color3uint8* src, int w, int h);
|
||||
void copyArray(const Color4uint8* src, int w, int h);
|
||||
|
||||
public:
|
||||
|
||||
const class ImageFormat* format() const;
|
||||
|
||||
/** Creates an all-zero width x height image. */
|
||||
static Ref createEmpty(int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
|
||||
/** Creates a 0 x 0 image. */
|
||||
static Ref createEmpty(WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
|
||||
static Ref fromFile(const std::string& filename, WrapMode wrap = WrapMode::ERROR, GImage::Format fmt = GImage::AUTODETECT);
|
||||
|
||||
static Ref fromGImage(const class GImage& im, WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
static Ref fromArray(const class Color1uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color3uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color4uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color1* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color3* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color4* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
static Ref fromImage3(const ReferenceCountedPointer<class Image3>& im);
|
||||
static Ref fromImage1uint8(const ReferenceCountedPointer<class Image1uint8>& im);
|
||||
|
||||
/** Loads from any of the file formats supported by G3D::GImage. If there is an alpha channel on the input,
|
||||
it is stripped. */
|
||||
void load(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT);
|
||||
|
||||
/** Saves in any of the formats supported by G3D::GImage. */
|
||||
void save(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT);
|
||||
|
||||
/** Extracts color channel 0 <= c <= 2 and returns it as a new monochrome image. */
|
||||
ReferenceCountedPointer<class Image1uint8> getChannel(int c) const;
|
||||
};
|
||||
|
||||
} // G3D
|
||||
|
||||
#endif
|
||||
86
dep/include/g3dlite/G3D/Image4.h
Normal file
86
dep/include/g3dlite/G3D/Image4.h
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
/**
|
||||
@file Image4.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2007-01-31
|
||||
@edited 2007-01-31
|
||||
*/
|
||||
|
||||
|
||||
#ifndef G3D_IMAGE4_H
|
||||
#define G3D_IMAGE4_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Map2D.h"
|
||||
#include "G3D/Color4.h"
|
||||
#include "G3D/GImage.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
typedef ReferenceCountedPointer<class Image4> Image4Ref;
|
||||
|
||||
/**
|
||||
RGBA image with 32-bit floating point storage for each channel.
|
||||
|
||||
Whenever a method needs to convert from RGB to RGBA, A=1 is assumed.
|
||||
|
||||
Bilinear interpolation on Image4 is about 8x faster than on
|
||||
Image4uint8 due to the large cost of converting int->float on modern
|
||||
machines.
|
||||
|
||||
@sa G3D::Image4uint8, G3D::GImage.
|
||||
*/
|
||||
class Image4 : public Map2D<Color4, Color4> {
|
||||
public:
|
||||
|
||||
typedef Image4 Type;
|
||||
typedef ReferenceCountedPointer<class Image4> Ref;
|
||||
typedef Color4 Storage;
|
||||
typedef Color4 Compute;
|
||||
|
||||
protected:
|
||||
|
||||
Image4(int w, int h, WrapMode wrap);
|
||||
|
||||
void copyGImage(const class GImage& im);
|
||||
void copyArray(const Color1* src, int w, int h);
|
||||
void copyArray(const Color3* src, int w, int h);
|
||||
void copyArray(const Color4* src, int w, int h);
|
||||
void copyArray(const Color1uint8* src, int w, int h);
|
||||
void copyArray(const Color3uint8* src, int w, int h);
|
||||
void copyArray(const Color4uint8* src, int w, int h);
|
||||
|
||||
public:
|
||||
|
||||
const class ImageFormat* format() const;
|
||||
|
||||
/** Creates an all-zero width x height image. */
|
||||
static Ref createEmpty(int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
/** Creates a 0 x 0 image. */
|
||||
static Ref createEmpty(WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
static Ref fromFile(const std::string& filename, WrapMode wrap = WrapMode::ERROR, GImage::Format fmt = GImage::AUTODETECT);
|
||||
|
||||
static Ref fromArray(const class Color1uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color3uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color4uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color1* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color3* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color4* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
static Ref fromImage4uint8(const ReferenceCountedPointer<class Image4uint8>& im);
|
||||
|
||||
static Ref fromGImage(const class GImage& im, WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
/** Loads from any of the file formats supported by G3D::GImage. */
|
||||
void load(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT);
|
||||
|
||||
/** Saves in any of the formats supported by G3D::GImage. */
|
||||
void save(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT);
|
||||
};
|
||||
|
||||
} // G3D
|
||||
|
||||
#endif
|
||||
85
dep/include/g3dlite/G3D/Image4uint8.h
Normal file
85
dep/include/g3dlite/G3D/Image4uint8.h
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
/**
|
||||
@file Image4uint8.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2007-01-31
|
||||
@edited 2007-01-31
|
||||
*/
|
||||
|
||||
#ifndef G3D_IMAGE4UINT8_H
|
||||
#define G3D_IMAGE4UINT8_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Map2D.h"
|
||||
#include "G3D/Color4uint8.h"
|
||||
#include "G3D/Color4.h"
|
||||
#include "G3D/GImage.h"
|
||||
#include "G3D/Image1uint8.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
typedef ReferenceCountedPointer<class Image4uint8> Image4uint8Ref;
|
||||
|
||||
/**
|
||||
Compact storage for RGBA 8-bit per channel images.
|
||||
|
||||
See also G3D::Image4, G3D::GImage
|
||||
*/
|
||||
class Image4uint8 : public Map2D<Color4uint8, Color4> {
|
||||
public:
|
||||
|
||||
typedef Image4uint8 Type;
|
||||
typedef Image4uint8Ref Ref;
|
||||
|
||||
protected:
|
||||
|
||||
Image4uint8(int w, int h, WrapMode wrap);
|
||||
|
||||
void copyGImage(const class GImage& im);
|
||||
void copyArray(const Color1* src, int w, int h);
|
||||
void copyArray(const Color3* src, int w, int h);
|
||||
void copyArray(const Color4* src, int w, int h);
|
||||
void copyArray(const Color1uint8* src, int w, int h);
|
||||
void copyArray(const Color3uint8* src, int w, int h);
|
||||
void copyArray(const Color4uint8* src, int w, int h);
|
||||
|
||||
public:
|
||||
|
||||
const class ImageFormat* format() const;
|
||||
|
||||
/** Creates an all-zero width x height image. */
|
||||
static Ref createEmpty(int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
|
||||
/** Creates a 0 x 0 image. */
|
||||
static Ref createEmpty(WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
|
||||
static Ref fromFile(const std::string& filename, WrapMode wrap = WrapMode::ERROR, GImage::Format fmt = GImage::AUTODETECT);
|
||||
|
||||
static Ref fromGImage(const class GImage& im, WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
static Ref fromArray(const class Color1uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color3uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color4uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color1* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color3* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color4* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
static Ref fromImage4(const ReferenceCountedPointer<class Image4>& im);
|
||||
|
||||
/** Loads from any of the file formats supported by G3D::GImage. If there is an alpha channel on the input,
|
||||
it is stripped. */
|
||||
void load(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT);
|
||||
|
||||
/** Saves in any of the formats supported by G3D::GImage. */
|
||||
void save(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT);
|
||||
|
||||
/** Extracts color channel 0 <= c <= 3 and returns it as a new monochrome image. */
|
||||
ReferenceCountedPointer<class Image1uint8> getChannel(int c) const;
|
||||
};
|
||||
|
||||
} // G3D
|
||||
|
||||
#endif
|
||||
419
dep/include/g3dlite/G3D/ImageFormat.h
Normal file
419
dep/include/g3dlite/G3D/ImageFormat.h
Normal file
|
|
@ -0,0 +1,419 @@
|
|||
/**
|
||||
@file ImageFormat.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2003-05-23
|
||||
@edited 2010-01-01
|
||||
*/
|
||||
|
||||
#ifndef GLG3D_ImageFormat_H
|
||||
#define GLG3D_ImageFormat_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Table.h"
|
||||
#include "G3D/enumclass.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/** Information about common image formats.
|
||||
Don't construct these; use the methods provided.
|
||||
|
||||
For most formats, the number indicates the number of bits per channel and a suffix of "F" indicates
|
||||
floating point. This does not hold for the YUV and DXT formats.*/
|
||||
class ImageFormat {
|
||||
public:
|
||||
|
||||
// Must update ImageFormat::name() when this enum changes.
|
||||
enum Code {
|
||||
CODE_NONE = -1,
|
||||
CODE_L8,
|
||||
CODE_L16,
|
||||
CODE_L16F,
|
||||
CODE_L32F,
|
||||
|
||||
CODE_A8,
|
||||
CODE_A16,
|
||||
CODE_A16F,
|
||||
CODE_A32F,
|
||||
|
||||
CODE_LA4,
|
||||
CODE_LA8,
|
||||
CODE_LA16,
|
||||
CODE_LA16F,
|
||||
CODE_LA32F,
|
||||
|
||||
CODE_RGB5,
|
||||
CODE_RGB5A1,
|
||||
CODE_RGB8,
|
||||
CODE_RGB10,
|
||||
CODE_RGB10A2,
|
||||
CODE_RGB16,
|
||||
CODE_RGB16F,
|
||||
CODE_RGB32F,
|
||||
CODE_R11G11B10F,
|
||||
CODE_RGB9E5F,
|
||||
|
||||
CODE_RGB8I,
|
||||
CODE_RGB8UI,
|
||||
|
||||
CODE_ARGB8,
|
||||
CODE_BGR8,
|
||||
|
||||
CODE_RG8,
|
||||
CODE_RG8I,
|
||||
CODE_RG8UI,
|
||||
|
||||
CODE_RGBA8,
|
||||
CODE_RGBA16,
|
||||
CODE_RGBA16F,
|
||||
CODE_RGBA32F,
|
||||
|
||||
CODE_RGBA32UI,
|
||||
|
||||
CODE_BAYER_RGGB8,
|
||||
CODE_BAYER_GRBG8,
|
||||
CODE_BAYER_GBRG8,
|
||||
CODE_BAYER_BGGR8,
|
||||
CODE_BAYER_RGGB32F,
|
||||
CODE_BAYER_GRBG32F,
|
||||
CODE_BAYER_GBRG32F,
|
||||
CODE_BAYER_BGGR32F,
|
||||
|
||||
CODE_HSV8,
|
||||
CODE_HSV32F,
|
||||
|
||||
CODE_YUV420_PLANAR,
|
||||
CODE_YUV422,
|
||||
CODE_YUV444,
|
||||
|
||||
CODE_RGB_DXT1,
|
||||
CODE_RGBA_DXT1,
|
||||
CODE_RGBA_DXT3,
|
||||
CODE_RGBA_DXT5,
|
||||
|
||||
CODE_SRGB8,
|
||||
CODE_SRGBA8,
|
||||
|
||||
CODE_SL8,
|
||||
CODE_SLA8,
|
||||
|
||||
CODE_SRGB_DXT1,
|
||||
CODE_SRGBA_DXT1,
|
||||
CODE_SRGBA_DXT3,
|
||||
CODE_SRGBA_DXT5,
|
||||
|
||||
CODE_DEPTH16,
|
||||
CODE_DEPTH24,
|
||||
CODE_DEPTH32,
|
||||
CODE_DEPTH32F,
|
||||
|
||||
CODE_STENCIL1,
|
||||
CODE_STENCIL4,
|
||||
CODE_STENCIL8,
|
||||
CODE_STENCIL16,
|
||||
|
||||
CODE_DEPTH24_STENCIL8,
|
||||
|
||||
CODE_NUM
|
||||
};
|
||||
|
||||
enum ColorSpace {
|
||||
COLOR_SPACE_NONE,
|
||||
COLOR_SPACE_RGB,
|
||||
COLOR_SPACE_HSV,
|
||||
COLOR_SPACE_YUV,
|
||||
COLOR_SPACE_SRGB
|
||||
};
|
||||
|
||||
enum BayerPattern {
|
||||
BAYER_PATTERN_NONE,
|
||||
BAYER_PATTERN_RGGB,
|
||||
BAYER_PATTERN_GRBG,
|
||||
BAYER_PATTERN_GBRG,
|
||||
BAYER_PATTERN_BGGR
|
||||
};
|
||||
|
||||
/** Number of channels (1 for a depth texture). */
|
||||
int numComponents;
|
||||
bool compressed;
|
||||
|
||||
/** Useful for serializing. */
|
||||
Code code;
|
||||
|
||||
ColorSpace colorSpace;
|
||||
|
||||
/** If this is a Bayer format, what is the pattern. */
|
||||
BayerPattern bayerPattern;
|
||||
|
||||
/** The OpenGL format equivalent to this one, e.g, GL_RGB8 Zero if there is no equivalent. This is actually a GLenum */
|
||||
int openGLFormat;
|
||||
|
||||
/** The OpenGL base format equivalent to this one (e.g., GL_RGB, GL_ALPHA). Zero if there is no equivalent. */
|
||||
int openGLBaseFormat;
|
||||
|
||||
int luminanceBits;
|
||||
|
||||
/** Number of bits per pixel storage for alpha values; Zero for compressed textures and non-RGB. */
|
||||
int alphaBits;
|
||||
|
||||
/** Number of bits per pixel storage for red values; Zero for compressed textures and non-RGB. */
|
||||
int redBits;
|
||||
|
||||
/** Number of bits per pixel storage for green values; Zero for compressed textures and non-RGB. */
|
||||
int greenBits;
|
||||
|
||||
/** Number of bits per pixel storage for blue values; Zero for compressed textures and non-RGB. */
|
||||
int blueBits;
|
||||
|
||||
/** Number of bits per pixel */
|
||||
int stencilBits;
|
||||
|
||||
/** Number of depth bits (for depth textures; e.g. shadow maps) */
|
||||
int depthBits;
|
||||
|
||||
/** Amount of CPU memory per pixel when packed into an array, discounting any end-of-row padding. */
|
||||
int cpuBitsPerPixel;
|
||||
|
||||
/** Amount of CPU memory per pixel when packed into an array, discounting any end-of-row padding.
|
||||
@deprecated Use cpuBitsPerPixel*/
|
||||
int packedBitsPerTexel;
|
||||
|
||||
/**
|
||||
Amount of GPU memory per pixel on most graphics cards, for formats supported by OpenGL. This is
|
||||
only an estimate--the actual amount of memory may be different on your actual card.
|
||||
|
||||
This may be greater than the sum of the per-channel bits
|
||||
because graphics cards need to pad to the nearest 1, 2, or
|
||||
4 bytes.
|
||||
*/
|
||||
int openGLBitsPerPixel;
|
||||
|
||||
/** @deprecated Use openGLBitsPerPixel */
|
||||
int hardwareBitsPerTexel;
|
||||
|
||||
/** The OpenGL bytes (type) format of the data buffer used with this texture format, e.g., GL_UNSIGNED_BYTE */
|
||||
int openGLDataFormat;
|
||||
|
||||
/** True if there is no alpha channel for this texture. */
|
||||
bool opaque;
|
||||
|
||||
/** True if the bit depths specified are for float formats. */
|
||||
bool floatingPoint;
|
||||
|
||||
/** Human readable name of this format.*/
|
||||
const std::string& name() const;
|
||||
|
||||
/** Takes the same values that name() returns */
|
||||
static const ImageFormat* fromString(const std::string& s);
|
||||
|
||||
private:
|
||||
|
||||
ImageFormat
|
||||
(int numComponents,
|
||||
bool compressed,
|
||||
int glFormat,
|
||||
int glBaseFormat,
|
||||
int luminanceBits,
|
||||
int alphaBits,
|
||||
int redBits,
|
||||
int greenBits,
|
||||
int blueBits,
|
||||
int depthBits,
|
||||
int stencilBits,
|
||||
int hardwareBitsPerTexel,
|
||||
int packedBitsPerTexel,
|
||||
int glDataFormat,
|
||||
bool opaque,
|
||||
bool floatingPoint,
|
||||
Code code,
|
||||
ColorSpace colorSpace,
|
||||
BayerPattern bayerPattern = BAYER_PATTERN_NONE);
|
||||
|
||||
public:
|
||||
|
||||
static const ImageFormat* L8();
|
||||
|
||||
static const ImageFormat* L16();
|
||||
|
||||
static const ImageFormat* L16F();
|
||||
|
||||
static const ImageFormat* L32F();
|
||||
|
||||
static const ImageFormat* A8();
|
||||
|
||||
static const ImageFormat* A16();
|
||||
|
||||
static const ImageFormat* A16F();
|
||||
|
||||
static const ImageFormat* A32F();
|
||||
|
||||
static const ImageFormat* LA4();
|
||||
|
||||
static const ImageFormat* LA8();
|
||||
|
||||
static const ImageFormat* LA16();
|
||||
|
||||
static const ImageFormat* LA16F();
|
||||
|
||||
static const ImageFormat* LA32F();
|
||||
|
||||
static const ImageFormat* BGR8();
|
||||
|
||||
static const ImageFormat* RG8();
|
||||
static const ImageFormat* RG8I();
|
||||
static const ImageFormat* RG8UI();
|
||||
|
||||
static const ImageFormat* RGB5();
|
||||
|
||||
static const ImageFormat* RGB5A1();
|
||||
|
||||
static const ImageFormat* RGB8();
|
||||
|
||||
static const ImageFormat* RGB10();
|
||||
|
||||
static const ImageFormat* RGB10A2();
|
||||
|
||||
static const ImageFormat* RGB16();
|
||||
|
||||
static const ImageFormat* RGB16F();
|
||||
|
||||
static const ImageFormat* RGB32F();
|
||||
|
||||
static const ImageFormat* RGBA8();
|
||||
|
||||
static const ImageFormat* RGBA16();
|
||||
|
||||
static const ImageFormat* RGBA16F();
|
||||
|
||||
static const ImageFormat* RGBA32F();
|
||||
|
||||
static const ImageFormat* RGBA32UI();
|
||||
|
||||
static const ImageFormat* R11G11B10F();
|
||||
|
||||
static const ImageFormat* RGB9E5F();
|
||||
|
||||
static const ImageFormat* RGB8I();
|
||||
|
||||
static const ImageFormat* RGB8UI();
|
||||
|
||||
static const ImageFormat* RGB_DXT1();
|
||||
|
||||
static const ImageFormat* RGBA_DXT1();
|
||||
|
||||
static const ImageFormat* RGBA_DXT3();
|
||||
|
||||
static const ImageFormat* RGBA_DXT5();
|
||||
|
||||
static const ImageFormat* SRGB8();
|
||||
|
||||
static const ImageFormat* SRGBA8();
|
||||
|
||||
static const ImageFormat* SL8();
|
||||
|
||||
static const ImageFormat* SLA8();
|
||||
|
||||
static const ImageFormat* SRGB_DXT1();
|
||||
|
||||
static const ImageFormat* SRGBA_DXT1();
|
||||
|
||||
static const ImageFormat* SRGBA_DXT3();
|
||||
|
||||
static const ImageFormat* SRGBA_DXT5();
|
||||
|
||||
static const ImageFormat* DEPTH16();
|
||||
|
||||
static const ImageFormat* DEPTH24();
|
||||
|
||||
static const ImageFormat* DEPTH32();
|
||||
|
||||
static const ImageFormat* DEPTH32F();
|
||||
|
||||
static const ImageFormat* STENCIL1();
|
||||
|
||||
static const ImageFormat* STENCIL4();
|
||||
|
||||
static const ImageFormat* STENCIL8();
|
||||
|
||||
static const ImageFormat* STENCIL16();
|
||||
|
||||
static const ImageFormat* DEPTH24_STENCIL8();
|
||||
|
||||
static const ImageFormat* YUV420_PLANAR();
|
||||
|
||||
static const ImageFormat* YUV422();
|
||||
|
||||
static const ImageFormat* YUV444();
|
||||
|
||||
/**
|
||||
NULL pointer; indicates that the G3D::Texture class should choose
|
||||
either RGBA8 or RGB8 depending on the presence of an alpha channel
|
||||
in the input.
|
||||
*/
|
||||
static const ImageFormat* AUTO() { return NULL; }
|
||||
|
||||
/** Returns DEPTH16, DEPTH24, or DEPTH32 according to the bits
|
||||
specified. You can use "glGetInteger(GL_DEPTH_BITS)" to match
|
||||
the screen's format.*/
|
||||
static const ImageFormat* depth(int depthBits = 24);
|
||||
|
||||
/** Returns STENCIL1, STENCIL4, STENCIL8 or STENCIL16 according to the bits
|
||||
specified. You can use "glGetInteger(GL_STENCIL_BITS)" to match
|
||||
the screen's format.*/
|
||||
static const ImageFormat* stencil(int bits = 8);
|
||||
|
||||
/** Returns the matching ImageFormat* identified by the Code. May return NULL
|
||||
if this format's code is reserved but not yet implemented by G3D. */
|
||||
static const ImageFormat* fromCode(ImageFormat::Code code);
|
||||
|
||||
|
||||
|
||||
/** For use with ImageFormat::convert. */
|
||||
class BayerAlgorithm {
|
||||
public:
|
||||
enum Value {
|
||||
NEAREST,
|
||||
BILINEAR,
|
||||
MHC,
|
||||
HIGH_QUALITY = MHC
|
||||
};
|
||||
private:
|
||||
|
||||
Value value;
|
||||
|
||||
public:
|
||||
|
||||
G3D_DECLARE_ENUM_CLASS_METHODS(BayerAlgorithm);
|
||||
};
|
||||
|
||||
/** Converts between arbitrary formats on the CPU. Not all format conversions are supported or directly supported.
|
||||
Formats without direct conversions will attempt to convert through RGBA first.
|
||||
|
||||
A conversion routine might only support source or destination padding or y inversion or none.
|
||||
If support is needed and not available in any of the direct conversion routines, then no conversion is done.
|
||||
|
||||
YUV422 expects data in YUY2 format (Y, U, Y2, v). Most YUV formats require width and heights that are multiples of 2.
|
||||
|
||||
Returns true if a conversion was available, false if none occurred.
|
||||
*/
|
||||
static bool convert(const Array<const void*>& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits,
|
||||
const Array<void*>& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits,
|
||||
bool invertY = false, BayerAlgorithm bayerAlg = BayerAlgorithm::HIGH_QUALITY);
|
||||
|
||||
/* Checks if a conversion between two formats is available. */
|
||||
static bool conversionAvailable(const ImageFormat* srcFormat, int srcRowPadBits, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY = false);
|
||||
};
|
||||
|
||||
typedef ImageFormat TextureFormat;
|
||||
|
||||
}
|
||||
|
||||
template <>
|
||||
struct HashTrait<const G3D::ImageFormat*> {
|
||||
static size_t hashCode(const G3D::ImageFormat* key) { return reinterpret_cast<size_t>(key); }
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
55
dep/include/g3dlite/G3D/Intersect.h
Normal file
55
dep/include/g3dlite/G3D/Intersect.h
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
/**
|
||||
@file Intersect.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2009-06-29
|
||||
@edited 2009-06-29
|
||||
|
||||
Copyright 2000-2009, Morgan McGuire.
|
||||
All rights reserved.
|
||||
|
||||
From the G3D Innovation Engine
|
||||
http://g3d.sf.net
|
||||
*/
|
||||
#ifndef G3D_Intersect
|
||||
#define G3D_Intersect
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Ray.h"
|
||||
#include "G3D/AABox.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
@beta
|
||||
*/
|
||||
class Intersect {
|
||||
public:
|
||||
|
||||
/** \brief Returns true if the intersection of the ray and the solid box is non-empty.
|
||||
|
||||
\cite "Fast Ray / Axis-Aligned Bounding Box Overlap Tests using Ray Slopes"
|
||||
by Martin Eisemann, Thorsten Grosch, Stefan Müller and Marcus Magnor
|
||||
Computer Graphics Lab, TU Braunschweig, Germany and
|
||||
University of Koblenz-Landau, Germany
|
||||
*/
|
||||
static bool __fastcall rayAABox(const Ray& ray, const AABox& box);
|
||||
|
||||
/** \brief Returns true if the intersection of the ray and the solid box is non-empty.
|
||||
|
||||
\param time If there is an intersection, set to the time to that intersection. If the ray origin is inside the box,
|
||||
this is a negative value indicating the distance backwards from the ray origin to the first intersection.
|
||||
\a time is not set if there is no intersection.
|
||||
|
||||
\cite Slope-Mul method from "Fast Ray / Axis-Aligned Bounding Box Overlap Tests using Ray Slopes"
|
||||
by Martin Eisemann, Thorsten Grosch, Stefan Müller and Marcus Magnor
|
||||
Computer Graphics Lab, TU Braunschweig, Germany and
|
||||
University of Koblenz-Landau, Germany
|
||||
*/
|
||||
static bool __fastcall rayAABox(const Ray& ray, const AABox& box, float& time);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
1667
dep/include/g3dlite/G3D/KDTree.h
Normal file
1667
dep/include/g3dlite/G3D/KDTree.h
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
Line class
|
||||
|
||||
@maintainer Morgan McGuire, matrix@graphics3d.com
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2001-06-02
|
||||
@edited 2006-02-28
|
||||
|
|
@ -38,6 +38,12 @@ public:
|
|||
/** Undefined (provided for creating Array<Line> only) */
|
||||
inline Line() {}
|
||||
|
||||
Line(class BinaryInput& b);
|
||||
|
||||
void serialize(class BinaryOutput& b) const;
|
||||
|
||||
void deserialize(class BinaryInput& b);
|
||||
|
||||
virtual ~Line() {}
|
||||
|
||||
/**
|
||||
|
|
@ -77,6 +83,20 @@ public:
|
|||
is no intersection, returns a point at infinity.
|
||||
*/
|
||||
Vector3 intersection(const Plane &plane) const;
|
||||
|
||||
|
||||
/** Finds the closest point to the two lines.
|
||||
|
||||
@param minDist Returns the minimum distance between the lines.
|
||||
|
||||
@cite http://objectmix.com/graphics/133793-coordinates-closest-points-pair-skew-lines.html
|
||||
*/
|
||||
Vector3 closestPoint(const Line& B, float& minDist) const;
|
||||
|
||||
inline Vector3 closestPoint(const Line& B) const {
|
||||
float m;
|
||||
return closestPoint(B, m);
|
||||
}
|
||||
};
|
||||
|
||||
};// namespace
|
||||
|
|
|
|||
115
dep/include/g3dlite/G3D/LineSegment.h
Normal file
115
dep/include/g3dlite/G3D/LineSegment.h
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
/**
|
||||
@file LineSegment.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2003-02-08
|
||||
@edited 2008-02-02
|
||||
*/
|
||||
|
||||
#ifndef G3D_LINESEGMENT_H
|
||||
#define G3D_LINESEGMENT_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Vector3.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
An finite segment of an infinite 3D line.
|
||||
*/
|
||||
class LineSegment {
|
||||
protected:
|
||||
|
||||
Vector3 _point;
|
||||
|
||||
/** Not normalized */
|
||||
Vector3 direction;
|
||||
|
||||
LineSegment(const Vector3& __point, const Vector3& _direction) : _point(__point), direction(_direction) {
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
inline LineSegment() : _point(Vector3::zero()), direction(Vector3::zero()) {}
|
||||
|
||||
LineSegment(class BinaryInput& b);
|
||||
|
||||
void serialize(class BinaryOutput& b) const;
|
||||
|
||||
void deserialize(class BinaryInput& b);
|
||||
|
||||
virtual ~LineSegment() {}
|
||||
|
||||
/**
|
||||
* Constructs a line from two (not equal) points.
|
||||
*/
|
||||
static LineSegment fromTwoPoints(const Vector3 &point1, const Vector3 &point2) {
|
||||
return LineSegment(point1, point2 - point1);
|
||||
}
|
||||
|
||||
/** Call with 0 or 1 */
|
||||
Vector3 point(int i) const;
|
||||
|
||||
inline float length() const {
|
||||
return direction.magnitude();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the closest point on the line segment to point.
|
||||
*/
|
||||
Vector3 closestPoint(const Vector3 &point) const;
|
||||
|
||||
/**
|
||||
Returns the distance between point and the line
|
||||
*/
|
||||
double distance(const Vector3& p) const {
|
||||
return (closestPoint(p) - p).magnitude();
|
||||
}
|
||||
|
||||
double distanceSquared(const Vector3& p) const {
|
||||
return (closestPoint(p) - p).squaredMagnitude();
|
||||
}
|
||||
|
||||
/** Returns true if some part of this segment is inside the sphere */
|
||||
bool intersectsSolidSphere(const class Sphere& s) const;
|
||||
|
||||
Vector3 randomPoint() const;
|
||||
|
||||
};
|
||||
|
||||
|
||||
class LineSegment2D {
|
||||
private:
|
||||
|
||||
Vector2 m_origin;
|
||||
|
||||
/** Not normalized */
|
||||
Vector2 m_direction;
|
||||
|
||||
/** Length of m_direction */
|
||||
float m_length;
|
||||
|
||||
public:
|
||||
|
||||
LineSegment2D() {}
|
||||
|
||||
static LineSegment2D fromTwoPoints(const Vector2& p0, const Vector2& p1);
|
||||
|
||||
/** Returns the intersection of these segements (including
|
||||
testing endpoints), or Vector2::inf() if they do not intersect. */
|
||||
Vector2 intersection(const LineSegment2D& other) const;
|
||||
|
||||
Vector2 point(int i) const;
|
||||
|
||||
Vector2 closestPoint(const Vector2& Q) const;
|
||||
|
||||
float distance(const Vector2& p) const;
|
||||
|
||||
float length() const;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
#endif
|
||||
109
dep/include/g3dlite/G3D/Log.h
Normal file
109
dep/include/g3dlite/G3D/Log.h
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
/**
|
||||
@file Log.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
@cite Backtrace by Aaron Orenstein
|
||||
@created 2001-08-04
|
||||
@edited 2005-11-04
|
||||
*/
|
||||
|
||||
#ifndef G3D_LOG_H
|
||||
#define G3D_LOG_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include "G3D/platform.h"
|
||||
|
||||
#ifndef G3D_WIN32
|
||||
#include <stdarg.h>
|
||||
#endif
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/** Prints to the common system log, log.txt, which is usually
|
||||
in the working directory of the program. If your disk is
|
||||
not writable or is slow, it will attempt to write to "c:/tmp/log.txt" or
|
||||
"c:/temp/log.txt" on Windows systems instead.
|
||||
|
||||
Unlike printf or debugPrintf,
|
||||
this function guarantees that all output is committed before it returns.
|
||||
This is very useful for debugging a crash, which might hide the last few
|
||||
buffered print statements otherwise.
|
||||
|
||||
Many G3D routines write useful warnings and debugging information to the
|
||||
system log, which makes it a good first place to go when tracking down
|
||||
a problem.
|
||||
*/
|
||||
void logPrintf(const char* fmt, ...);
|
||||
|
||||
/** Does not flush the buffer; follow up with a logPrintf to force the flush. */
|
||||
void logLazyPrintf(const char* fmt, ...);
|
||||
|
||||
/**
|
||||
System log for debugging purposes. The first log opened
|
||||
is the "common log" and can be accessed with the static
|
||||
method common(). If you access common() and a common log
|
||||
does not yet exist, one is created for you.
|
||||
*/
|
||||
class Log {
|
||||
private:
|
||||
|
||||
/**
|
||||
Log messages go here.
|
||||
*/
|
||||
FILE* logFile;
|
||||
|
||||
std::string filename;
|
||||
|
||||
static Log* commonLog;
|
||||
|
||||
int stripFromStackBottom;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
@param stripFromStackBottom Number of call stacks to strip from the
|
||||
bottom of the stack when printing a trace. Useful for hiding
|
||||
routines like "main" and "WinMain". If the specified file cannot
|
||||
be opened for some reason, tries to open "c:/tmp/log.txt" or
|
||||
"c:/temp/log.txt" instead.
|
||||
*/
|
||||
Log(const std::string& filename = "log.txt",
|
||||
int stripFromStackBottom = 0);
|
||||
|
||||
virtual ~Log();
|
||||
|
||||
/**
|
||||
Returns the handle to the file log.
|
||||
*/
|
||||
FILE* getFile() const;
|
||||
|
||||
/**
|
||||
Marks the beginning of a logfile section.
|
||||
*/
|
||||
void section(const std::string& s);
|
||||
|
||||
/**
|
||||
Given arguments like printf, writes characters to the debug text overlay.
|
||||
*/
|
||||
// We want G3D_CHECK_PRINTF_ARGS here, but that conflicts with the
|
||||
// overload.
|
||||
void __cdecl printf(const char* fmt, ...) G3D_CHECK_PRINTF_METHOD_ARGS;
|
||||
|
||||
void __cdecl vprintf(const char*, va_list argPtr) G3D_CHECK_VPRINTF_METHOD_ARGS;
|
||||
/** Does not flush */
|
||||
void __cdecl lazyvprintf(const char*, va_list argPtr) G3D_CHECK_VPRINTF_METHOD_ARGS;
|
||||
|
||||
static Log* common();
|
||||
|
||||
static std::string getCommonLogFilename();
|
||||
|
||||
void print(const std::string& s);
|
||||
|
||||
|
||||
void println(const std::string& s);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
667
dep/include/g3dlite/G3D/Map2D.h
Normal file
667
dep/include/g3dlite/G3D/Map2D.h
Normal file
|
|
@ -0,0 +1,667 @@
|
|||
/**
|
||||
@file Map2D.h
|
||||
|
||||
More flexible support than provided by G3D::GImage.
|
||||
|
||||
@maintainer Morgan McGuire, morgan@cs.brown.edu
|
||||
@created 2004-10-10
|
||||
@edited 2009-03-24
|
||||
*/
|
||||
#ifndef G3D_Map2D_h
|
||||
#define G3D_Map2D_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/Array.h"
|
||||
#include "G3D/vectorMath.h"
|
||||
#include "G3D/Vector2int16.h"
|
||||
#include "G3D/ReferenceCount.h"
|
||||
#include "G3D/AtomicInt32.h"
|
||||
#include "G3D/GThread.h"
|
||||
#include "G3D/Rect2D.h"
|
||||
#include "G3D/WrapMode.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace G3D {
|
||||
namespace _internal {
|
||||
|
||||
/** The default compute type for a type is the type itself. */
|
||||
template<typename Storage> class _GetComputeType {
|
||||
public:
|
||||
typedef Storage Type;
|
||||
};
|
||||
|
||||
} // _internal
|
||||
} // G3D
|
||||
|
||||
// This weird syntax is needed to support VC6, which doesn't
|
||||
// properly implement template overloading.
|
||||
#define DECLARE_COMPUTE_TYPE(StorageType, ComputeType) \
|
||||
namespace G3D { \
|
||||
namespace _internal { \
|
||||
template<> class _GetComputeType < StorageType > { \
|
||||
public: \
|
||||
typedef ComputeType Type; \
|
||||
}; \
|
||||
} \
|
||||
}
|
||||
|
||||
DECLARE_COMPUTE_TYPE( float32, float64)
|
||||
DECLARE_COMPUTE_TYPE( float64, float64)
|
||||
|
||||
DECLARE_COMPUTE_TYPE( int8, float32)
|
||||
DECLARE_COMPUTE_TYPE( int16, float32)
|
||||
DECLARE_COMPUTE_TYPE( int32, float64)
|
||||
DECLARE_COMPUTE_TYPE( int64, float64)
|
||||
|
||||
DECLARE_COMPUTE_TYPE( uint8, float32)
|
||||
DECLARE_COMPUTE_TYPE( uint16, float32)
|
||||
DECLARE_COMPUTE_TYPE( uint32, float64)
|
||||
DECLARE_COMPUTE_TYPE( uint64, float64)
|
||||
|
||||
DECLARE_COMPUTE_TYPE( Vector2, Vector2)
|
||||
DECLARE_COMPUTE_TYPE( Vector2int16, Vector2)
|
||||
|
||||
DECLARE_COMPUTE_TYPE( Vector3, Vector3)
|
||||
DECLARE_COMPUTE_TYPE( Vector3int16, Vector3)
|
||||
|
||||
DECLARE_COMPUTE_TYPE( Vector4, Vector4)
|
||||
|
||||
DECLARE_COMPUTE_TYPE( Color3, Color3)
|
||||
DECLARE_COMPUTE_TYPE( Color3uint8, Color3)
|
||||
|
||||
DECLARE_COMPUTE_TYPE( Color4, Color4)
|
||||
DECLARE_COMPUTE_TYPE( Color4uint8, Color4)
|
||||
#undef DECLARE_COMPUTE_TYPE
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
Map of values across a discrete 2D plane. Can be thought of as a generic class for 2D images,
|
||||
allowing flexibility as to pixel format and convenient methods.
|
||||
In fact, the "pixels" can be any values
|
||||
on a grid that can be sensibly interpolated--RGB colors, scalars, 4D vectors, and so on.
|
||||
|
||||
Other "image" classes in G3D:
|
||||
|
||||
G3D::GImage - Supports file formats, fast, Color3uint8 and Color4uint8 formats. No interpolation.
|
||||
|
||||
G3D::Texture::Ref - Represents image on the graphics card (not directly readable on the CPU). Supports 2D, 3D, and a variety of interpolation methods, loads file formats.
|
||||
|
||||
G3D::Image3 - A subclass of Map2D<Color3> that supports image loading and saving and conversion to Texture.
|
||||
|
||||
G3D::Image4 - A subclass of Map2D<Color4> that supports image loading and saving and conversion to Texture.
|
||||
|
||||
G3D::Image3uint8 - A subclass of Map2D<Color3uint8> that supports image loading and saving and conversion to Texture.
|
||||
|
||||
G3D::Image4uint8 - A subclass of Map2D<Color4uint8> that supports image loading and saving and conversion to Texture.
|
||||
|
||||
There are two type parameters-- the first (@ Storage) is the type
|
||||
used to store the "pixel" values efficiently and
|
||||
the second (@a Compute) is
|
||||
the type operated on by computation. The Compute::Compute(Storage&) constructor
|
||||
is used to convert between storage and computation types.
|
||||
@a Storage is often an integer version of @a Compute, for example
|
||||
<code>Map2D<double, uint8></code>. By default, the computation type is:
|
||||
|
||||
<pre>
|
||||
Storage Computation
|
||||
|
||||
uint8 float32
|
||||
uint16 float32
|
||||
uint32 float64
|
||||
uint64 float64
|
||||
|
||||
int8 float32
|
||||
int16 float32
|
||||
int32 float64
|
||||
int64 float64
|
||||
|
||||
float32 float64
|
||||
float64 float64
|
||||
|
||||
Vector2 Vector2
|
||||
Vector2int16 Vector2
|
||||
|
||||
Vector3 Vector3
|
||||
Vector3int16 Vector3
|
||||
|
||||
Vector4 Vector4
|
||||
|
||||
Color3 Color3
|
||||
Color3uint8 Color3
|
||||
|
||||
Color4 Color4
|
||||
Color4uint8 Color4
|
||||
</pre>
|
||||
Any other storage type defaults to itself as the computation type.
|
||||
|
||||
The computation type can be any that
|
||||
supports lerp, +, -, *, /, and an empty constructor.
|
||||
|
||||
Assign value:
|
||||
|
||||
<code>im->set(x, y, 7);</code> or
|
||||
<code>im->get(x, y) = 7;</code>
|
||||
|
||||
Read value:
|
||||
|
||||
<code>int c = im(x, y);</code>
|
||||
|
||||
Can also sample with nearest neighbor, bilinear, and bicubic
|
||||
interpolation.
|
||||
|
||||
Sampling follows OpenGL conventions, where
|
||||
pixel values represent grid points and (0.5, 0.5) is half-way
|
||||
between two vertical and two horizontal grid points.
|
||||
To draw an image of dimensions w x h with nearest neighbor
|
||||
sampling, render pixels from [0, 0] to [w - 1, h - 1].
|
||||
|
||||
Under the WrapMode::CLAMP wrap mode, the value of bilinear interpolation
|
||||
becomes constant outside [1, w - 2] horizontally. Nearest neighbor
|
||||
interpolation is constant outside [0, w - 1] and bicubic outside
|
||||
[3, w - 4]. The class does not offer quadratic interpolation because
|
||||
the interpolation filter could not center over a pixel.
|
||||
|
||||
@author Morgan McGuire, http://graphics.cs.williams.edu
|
||||
*/
|
||||
template< typename Storage,
|
||||
typename Compute = typename G3D::_internal::_GetComputeType<Storage>::Type>
|
||||
class Map2D : public ReferenceCountedObject {
|
||||
|
||||
//
|
||||
// It doesn't make sense to automatically convert from Compute back to Storage
|
||||
// because the rounding rule (and scaling) is application dependent.
|
||||
// Thus the interpolation methods all return type Compute.
|
||||
//
|
||||
|
||||
public:
|
||||
|
||||
typedef Storage StorageType;
|
||||
typedef Compute ComputeType;
|
||||
typedef Map2D<Storage, Compute> Type;
|
||||
typedef ReferenceCountedPointer<Map2D> Ref;
|
||||
|
||||
protected:
|
||||
|
||||
Storage ZERO;
|
||||
|
||||
/** Width, in pixels. */
|
||||
uint32 w;
|
||||
|
||||
/** Height, in pixels. */
|
||||
uint32 h;
|
||||
|
||||
WrapMode _wrapMode;
|
||||
|
||||
/** 0 if no mutating method has been invoked
|
||||
since the last call to setChanged(); */
|
||||
AtomicInt32 m_changed;
|
||||
|
||||
Array<Storage> data;
|
||||
|
||||
/** Handles the exceptional cases from get */
|
||||
const Storage& slowGet(int x, int y, WrapMode wrap) {
|
||||
switch (wrap) {
|
||||
case WrapMode::CLAMP:
|
||||
return fastGet(iClamp(x, 0, w - 1), iClamp(y, 0, h - 1));
|
||||
|
||||
case WrapMode::TILE:
|
||||
return fastGet(iWrap(x, w), iWrap(y, h));
|
||||
|
||||
case WrapMode::ZERO:
|
||||
return ZERO;
|
||||
|
||||
case WrapMode::ERROR:
|
||||
alwaysAssertM(((uint32)x < w) && ((uint32)y < h),
|
||||
format("Index out of bounds: (%d, %d), w = %d, h = %d",
|
||||
x, y, w, h));
|
||||
|
||||
// intentionally fall through
|
||||
case WrapMode::IGNORE:
|
||||
// intentionally fall through
|
||||
default:
|
||||
{
|
||||
static Storage temp;
|
||||
return temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/** Unsafe access to the underlying data structure with no wrapping support; requires that (x, y) is in bounds. */
|
||||
inline const Storage& fastGet(int x, int y) const {
|
||||
debugAssert(((uint32)x < w) && ((uint32)y < h));
|
||||
return data[x + y * w];
|
||||
}
|
||||
|
||||
/** Unsafe access to the underlying data structure with no wrapping support; requires that (x, y) is in bounds. */
|
||||
inline void fastSet(int x, int y, const Storage& v) {
|
||||
debugAssert(((uint32)x < w) && ((uint32)y < h));
|
||||
data[x + y * w] = v;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/** Given four control points and a value on the range [0, 1)
|
||||
evaluates the Catmull-rom spline between the times of the
|
||||
middle two control points */
|
||||
Compute bicubic(const Compute* ctrl, double s) const {
|
||||
|
||||
// f = B * S * ctrl'
|
||||
|
||||
// B matrix: Catmull-Rom spline basis
|
||||
static const double B[4][4] = {
|
||||
{ 0.0, -0.5, 1.0, -0.5},
|
||||
{ 1.0, 0.0, -2.5, 1.5},
|
||||
{ 0.0, 0.5, 2.0, -1.5},
|
||||
{ 0.0, 0.0, -0.5, 0.5}};
|
||||
|
||||
// S: Powers of the fraction
|
||||
double S[4];
|
||||
double s2 = s * s;
|
||||
S[0] = 1.0;
|
||||
S[1] = s;
|
||||
S[2] = s2;
|
||||
S[3] = s2 * s;
|
||||
|
||||
Compute sum(ZERO);
|
||||
|
||||
for (int c = 0; c < 4; ++c) {
|
||||
double coeff = 0.0;
|
||||
for (int power = 0; power < 4; ++power) {
|
||||
coeff += B[c][power] * S[power];
|
||||
}
|
||||
sum += ctrl[c] * coeff;
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
|
||||
Map2D(int w, int h, WrapMode wrap) : w(0), h(0), _wrapMode(wrap), m_changed(1) {
|
||||
ZERO = Storage(Compute(Storage()) * 0);
|
||||
resize(w, h);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
Although Map2D is not threadsafe (except for the setChanged() method),
|
||||
you can use this mutex to create your own threadsafe access to a Map2D.
|
||||
Not used by the default implementation.
|
||||
*/
|
||||
GMutex mutex;
|
||||
|
||||
static Ref create(int w = 0, int h = 0, WrapMode wrap = WrapMode::ERROR) {
|
||||
return new Map2D(w, h, wrap);
|
||||
}
|
||||
|
||||
/** Resizes without clearing, leaving garbage.
|
||||
*/
|
||||
void resize(uint32 newW, uint32 newH) {
|
||||
if ((newW != w) || (newH != h)) {
|
||||
w = newW;
|
||||
h = newH;
|
||||
data.resize(w * h);
|
||||
setChanged(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Returns true if this map has been written to since the last call to setChanged(false).
|
||||
This is useful if you are caching a texture map other value that must be recomputed
|
||||
whenever this changes.
|
||||
*/
|
||||
bool changed() {
|
||||
return m_changed.value() != 0;
|
||||
}
|
||||
|
||||
/** Set/unset the changed flag. */
|
||||
void setChanged(bool c) {
|
||||
m_changed = c ? 1 : 0;
|
||||
}
|
||||
|
||||
/** Returns a pointer to the underlying row-major data. There is no padding at the end of the row.
|
||||
Be careful--this will be reallocated during a resize. You should call setChanged(true) if you mutate the array.*/
|
||||
Storage* getCArray() {
|
||||
return data.getCArray();
|
||||
}
|
||||
|
||||
|
||||
const Storage* getCArray() const {
|
||||
return data.getCArray();
|
||||
}
|
||||
|
||||
|
||||
/** Row-major array. You should call setChanged(true) if you mutate the array. */
|
||||
Array<Storage>& getArray() {
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
const Array<Storage>& getArray() const {
|
||||
return data;
|
||||
}
|
||||
|
||||
/** is (x, y) strictly within the image bounds, or will it trigger some kind of wrap mode */
|
||||
inline bool inBounds(int x, int y) const {
|
||||
return (((uint32)x < w) && ((uint32)y < h));
|
||||
}
|
||||
|
||||
/** is (x, y) strictly within the image bounds, or will it trigger some kind of wrap mode */
|
||||
inline bool inBounds(const Vector2int16& v) const {
|
||||
return inBounds(v.x, v.y);
|
||||
}
|
||||
|
||||
/** Get the value at (x, y).
|
||||
|
||||
Note that the type of image->get(x, y) is
|
||||
the storage type, not the computation
|
||||
type. If the constructor promoting Storage to Compute rescales values
|
||||
(as, for example Color3(Color3uint8&) does), this will not match the value
|
||||
returned by Map2D::nearest.
|
||||
*/
|
||||
inline const Storage& get(int x, int y, WrapMode wrap) const {
|
||||
if (((uint32)x < w) && ((uint32)y < h)) {
|
||||
return data[x + y * w];
|
||||
} else {
|
||||
// Remove the const to allow a slowGet on this object
|
||||
// (we're returning a const reference so this is ok)
|
||||
return const_cast<Type*>(this)->slowGet(x, y, wrap);
|
||||
}
|
||||
# ifndef G3D_WIN32
|
||||
// gcc gives a useless warning that the above code might reach the end of the function;
|
||||
// we use this line to supress the warning.
|
||||
return ZERO;
|
||||
# endif
|
||||
}
|
||||
|
||||
inline const Storage& get(int x, int y) const {
|
||||
return get(x, y, _wrapMode);
|
||||
}
|
||||
|
||||
inline const Storage& get(const Vector2int16& p) const {
|
||||
return get(p.x, p.y, _wrapMode);
|
||||
}
|
||||
|
||||
inline const Storage& get(const Vector2int16& p, WrapMode wrap) const {
|
||||
return get(p.x, p.y, wrap);
|
||||
}
|
||||
|
||||
inline Storage& get(int x, int y, WrapMode wrap) {
|
||||
return const_cast<Storage&>(const_cast<const Type*>(this)->get(x, y, wrap));
|
||||
# ifndef G3D_WIN32
|
||||
// gcc gives a useless warning that the above code might reach the end of the function;
|
||||
// we use this line to supress the warning.
|
||||
return ZERO;
|
||||
# endif
|
||||
}
|
||||
|
||||
inline Storage& get(int x, int y) {
|
||||
return const_cast<Storage&>(const_cast<const Type*>(this)->get(x, y));
|
||||
# ifndef G3D_WIN32
|
||||
// gcc gives a useless warning that the above code might reach the end of the function;
|
||||
// we use this line to supress the warning.
|
||||
return ZERO;
|
||||
# endif
|
||||
}
|
||||
|
||||
inline Storage& get(const Vector2int16& p) {
|
||||
return get(p.x, p.y);
|
||||
}
|
||||
|
||||
/** Sets the changed flag to true */
|
||||
inline void set(const Vector2int16& p, const Storage& v) {
|
||||
set(p.x, p.y, v);
|
||||
}
|
||||
|
||||
/** Sets the changed flag to true */
|
||||
void set(int x, int y, const Storage& v, WrapMode wrap) {
|
||||
setChanged(true);
|
||||
if (((uint32)x < w) && ((uint32)y < h)) {
|
||||
// In bounds, wrapping isn't an issue.
|
||||
data[x + y * w] = v;
|
||||
} else {
|
||||
const_cast<Storage&>(slowGet(x, y, wrap)) = v;
|
||||
}
|
||||
}
|
||||
|
||||
void set(int x, int y, const Storage& v) {
|
||||
set(x, y, v, _wrapMode);
|
||||
}
|
||||
|
||||
|
||||
void setAll(const Storage& v) {
|
||||
for(int i = 0; i < data.size(); ++i) {
|
||||
data[i] = v;
|
||||
}
|
||||
setChanged(true);
|
||||
}
|
||||
|
||||
/** flips if @a flip is true*/
|
||||
void maybeFlipVertical(bool flip) {
|
||||
if (flip) {
|
||||
flipVertical();
|
||||
}
|
||||
}
|
||||
|
||||
virtual void flipVertical() {
|
||||
int halfHeight = h/2;
|
||||
Storage* d = data.getCArray();
|
||||
for (int y = 0; y < halfHeight; ++y) {
|
||||
int o1 = y * w;
|
||||
int o2 = (h - y - 1) * w;
|
||||
for (int x = 0; x < (int)w; ++x) {
|
||||
int i1 = o1 + x;
|
||||
int i2 = o2 + x;
|
||||
Storage temp = d[i1];
|
||||
d[i1] = d[i2];
|
||||
d[i2] = temp;
|
||||
}
|
||||
}
|
||||
setChanged(true);
|
||||
}
|
||||
|
||||
virtual void flipHorizontal() {
|
||||
int halfWidth = w / 2;
|
||||
Storage* d = data.getCArray();
|
||||
for (int x = 0; x < halfWidth; ++x) {
|
||||
for (int y = 0; y < (int)h; ++y) {
|
||||
int i1 = y * w + x;
|
||||
int i2 = y * w + (w - x - 1);
|
||||
Storage temp = d[i1];
|
||||
d[i1] = d[i2];
|
||||
d[i2] = temp;
|
||||
}
|
||||
}
|
||||
setChanged(true);
|
||||
}
|
||||
|
||||
/**
|
||||
Crops this map so that it only contains pixels between (x, y) and (x + w - 1, y + h - 1) inclusive.
|
||||
*/
|
||||
virtual void crop(int newX, int newY, int newW, int newH) {
|
||||
alwaysAssertM(newX + newW <= (int)w, "Cannot grow when cropping");
|
||||
alwaysAssertM(newY + newH <= (int)h, "Cannot grow when cropping");
|
||||
alwaysAssertM(newX >= 0 && newY >= 0, "Origin out of bounds.");
|
||||
|
||||
// Always safe to copy towards the upper left, provided
|
||||
// that we're iterating towards the lower right. This lets us avoid
|
||||
// reallocating the underlying array.
|
||||
for (int y = 0; y < newH; ++y) {
|
||||
for (int x = 0; x < newW; ++x) {
|
||||
data[x + y * newW] = data[(x + newX) + (y + newY) * w];
|
||||
}
|
||||
}
|
||||
|
||||
resize(newW, newH);
|
||||
}
|
||||
|
||||
/** iRounds to the nearest x0 and y0. */
|
||||
virtual void crop(const Rect2D& rect) {
|
||||
crop(iRound(rect.x0()), iRound(rect.y0()), iRound(rect.x1()) - iRound(rect.x0()), iRound(rect.y1()) - iRound(rect.y0()));
|
||||
}
|
||||
|
||||
/** Returns the nearest neighbor. Pixel values are considered
|
||||
to be at the upper left corner, so <code>image->nearest(x, y) == image(x, y)</code>
|
||||
*/
|
||||
inline Compute nearest(float x, float y, WrapMode wrap) const {
|
||||
int ix = iRound(x);
|
||||
int iy = iRound(y);
|
||||
return Compute(get(ix, iy, wrap));
|
||||
}
|
||||
|
||||
inline Compute nearest(float x, float y) const {
|
||||
return nearest(x, y, _wrapMode);
|
||||
}
|
||||
|
||||
inline Compute nearest(const Vector2& p) const {
|
||||
return nearest(p.x, p.y);
|
||||
}
|
||||
|
||||
/** Returns the average value of all elements of the map */
|
||||
Compute average() const {
|
||||
if ((w == 0) || (h == 0)) {
|
||||
return ZERO;
|
||||
}
|
||||
|
||||
// To avoid overflows, compute the average of row averages
|
||||
|
||||
Compute rowSum = ZERO;
|
||||
for (unsigned int y = 0; y < h; ++y) {
|
||||
Compute sum = ZERO;
|
||||
int offset = y * w;
|
||||
for (unsigned int x = 0; x < w; ++x) {
|
||||
sum += Compute(data[offset + x]);
|
||||
}
|
||||
rowSum += sum * (1.0f / w);
|
||||
}
|
||||
|
||||
return rowSum * (1.0f / h);
|
||||
}
|
||||
|
||||
/**
|
||||
Needs to access elements from (floor(x), floor(y))
|
||||
to (floor(x) + 1, floor(y) + 1) and will use
|
||||
the wrap mode appropriately (possibly generating
|
||||
out of bounds errors).
|
||||
|
||||
Guaranteed to match nearest(x, y) at integers. */
|
||||
Compute bilinear(float x, float y, WrapMode wrap) const {
|
||||
const int i = iFloor(x);
|
||||
const int j = iFloor(y);
|
||||
|
||||
const float fX = x - i;
|
||||
const float fY = y - j;
|
||||
|
||||
// Horizontal interpolation, first row
|
||||
const Compute& t0 = get(i, j, wrap);
|
||||
const Compute& t1 = get(i + 1, j, wrap);
|
||||
|
||||
// Horizontal interpolation, second row
|
||||
const Compute& t2 = get(i, j + 1, wrap);
|
||||
const Compute& t3 = get(i + 1, j + 1, wrap);
|
||||
|
||||
const Compute& A = lerp(t0, t1, fX);
|
||||
const Compute& B = lerp(t2, t3, fX);
|
||||
|
||||
// Vertical interpolation
|
||||
return lerp(A, B, fY);
|
||||
}
|
||||
|
||||
Compute bilinear(float x, float y) const {
|
||||
return bilinear(x, y, _wrapMode);
|
||||
}
|
||||
|
||||
inline Compute bilinear(const Vector2& p) const {
|
||||
return bilinear(p.x, p.y, _wrapMode);
|
||||
}
|
||||
|
||||
inline Compute bilinear(const Vector2& p, WrapMode wrap) const {
|
||||
return bilinear(p.x, p.y, wrap);
|
||||
}
|
||||
|
||||
/**
|
||||
Uses Catmull-Rom splines to interpolate between grid
|
||||
values. Guaranteed to match nearest(x, y) at integers.
|
||||
*/
|
||||
Compute bicubic(float x, float y, WrapMode wrap) const {
|
||||
int i = iFloor(x);
|
||||
int j = iFloor(y);
|
||||
float fX = x - i;
|
||||
float fY = y - j;
|
||||
|
||||
Compute vsample[4];
|
||||
for (int v = 0; v < 4; ++v) {
|
||||
|
||||
// Horizontal interpolation
|
||||
Compute hsample[4];
|
||||
for (int u = 0; u < 4; ++u) {
|
||||
hsample[u] = Compute(get(i + u - 1, j + v - 1, wrap));
|
||||
}
|
||||
|
||||
vsample[v] = bicubic(hsample, fX);
|
||||
}
|
||||
|
||||
// Vertical interpolation
|
||||
return bicubic(vsample, fY);
|
||||
}
|
||||
|
||||
Compute bicubic(float x, float y) const {
|
||||
return bicubic(x, y, _wrapMode);
|
||||
}
|
||||
|
||||
inline Compute bicubic(const Vector2& p, WrapMode wrap) const {
|
||||
return bicubic(p.x, p.y, wrap);
|
||||
}
|
||||
|
||||
inline Compute bicubic(const Vector2& p) const {
|
||||
return bicubic(p.x, p.y, _wrapMode);
|
||||
}
|
||||
|
||||
/** Pixel width */
|
||||
inline int32 width() const {
|
||||
return (int32)w;
|
||||
}
|
||||
|
||||
|
||||
/** Pixel height */
|
||||
inline int32 height() const {
|
||||
return (int32)h;
|
||||
}
|
||||
|
||||
|
||||
/** Dimensions in pixels */
|
||||
Vector2int16 size() const {
|
||||
return Vector2int16(w, h);
|
||||
}
|
||||
|
||||
/** Rectangle from (0, 0) to (w, h) */
|
||||
Rect2D rect2DBounds() const {
|
||||
return Rect2D::xywh(0, 0, w, h);
|
||||
}
|
||||
|
||||
/** Number of bytes occupied by the image data and this structure */
|
||||
size_t sizeInMemory() const {
|
||||
return data.size() * sizeof(Storage) + sizeof(*this);
|
||||
}
|
||||
|
||||
|
||||
WrapMode wrapMode() const {
|
||||
return _wrapMode;
|
||||
}
|
||||
|
||||
|
||||
void setWrapMode(WrapMode m) {
|
||||
_wrapMode = m;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif // G3D_IMAGE_H
|
||||
634
dep/include/g3dlite/G3D/Matrix.h
Normal file
634
dep/include/g3dlite/G3D/Matrix.h
Normal file
|
|
@ -0,0 +1,634 @@
|
|||
/**
|
||||
@file Matrix.h
|
||||
@author Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2005-10-23
|
||||
@edited 2007-07-18
|
||||
*/
|
||||
|
||||
#ifndef G3D_MATRIX_H
|
||||
#define G3D_MATRIX_H
|
||||
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/Vector3.h"
|
||||
#include "G3D/Vector4.h"
|
||||
#include "G3D/Matrix3.h"
|
||||
#include "G3D/Matrix4.h"
|
||||
#include "G3D/ReferenceCount.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
N x M matrix.
|
||||
|
||||
The actual data is tracked internally by a reference counted pointer;
|
||||
it is efficient to pass and assign Matrix objects because no data is actually copied.
|
||||
This avoids the headache of pointers and allows natural math notation:
|
||||
|
||||
<PRE>
|
||||
Matrix A, B, C;
|
||||
// ...
|
||||
|
||||
C = A * f(B);
|
||||
C = C.inverse();
|
||||
|
||||
A = Matrix::identity(4);
|
||||
C = A;
|
||||
C.set(0, 0, 2.0); // Triggers a copy of the data so that A remains unchanged.
|
||||
|
||||
// etc.
|
||||
|
||||
</PRE>
|
||||
|
||||
The Matrix::debugNumCopyOps and Matrix::debugNumAllocOps counters
|
||||
increment every time an operation forces the copy and allocation of matrices. You
|
||||
can use these to detect slow operations when efficiency is a major concern.
|
||||
|
||||
Some methods accept an output argument instead of returning a value. For example,
|
||||
<CODE>A = B.transpose()</CODE> can also be invoked as <CODE>B.transpose(A)</CODE>.
|
||||
The latter may be more efficient, since Matrix may be able to re-use the storage of
|
||||
A (if it has approximatly the right size and isn't currently shared with another matrix).
|
||||
|
||||
@sa G3D::Matrix3, G3D::Matrix4, G3D::Vector2, G3D::Vector3, G3D::Vector4, G3D::CoordinateFrame
|
||||
|
||||
@beta
|
||||
*/
|
||||
class Matrix {
|
||||
public:
|
||||
/**
|
||||
Internal precision. Currently float, but this may become a templated class in the future
|
||||
to allow operations like Matrix<double> and Matrix<ComplexFloat>.
|
||||
|
||||
Not necessarily a plain-old-data type (e.g., could ComplexFloat), but must be something
|
||||
with no constructor, that can be safely memcpyd, and that has a bit pattern of all zeros
|
||||
when zero.*/
|
||||
typedef float T;
|
||||
|
||||
/** Incremented every time the elements of a matrix are copied. Useful for profiling your
|
||||
own code that uses Matrix to determine when it is slow due to copying.*/
|
||||
static int debugNumCopyOps;
|
||||
|
||||
/** Incremented every time a new matrix object is allocated. Useful for profiling your
|
||||
own code that uses Matrix to determine when it is slow due to allocation.*/
|
||||
static int debugNumAllocOps;
|
||||
|
||||
private:
|
||||
public:
|
||||
|
||||
/** Used internally by Matrix.
|
||||
|
||||
Does not throw exceptions-- assumes the caller has taken care of
|
||||
argument checking. */
|
||||
class Impl : public ReferenceCountedObject {
|
||||
public:
|
||||
|
||||
static void* operator new(size_t size) {
|
||||
return System::malloc(size);
|
||||
}
|
||||
|
||||
static void operator delete(void* p) {
|
||||
System::free(p);
|
||||
}
|
||||
|
||||
~Impl();
|
||||
|
||||
private:
|
||||
friend class Matrix;
|
||||
|
||||
/** elt[r][c] = the element. Pointers into data.*/
|
||||
T** elt;
|
||||
|
||||
/** Row major data for the entire matrix. */
|
||||
T* data;
|
||||
|
||||
/** The number of rows */
|
||||
int R;
|
||||
|
||||
/** The number of columns */
|
||||
int C;
|
||||
|
||||
int dataSize;
|
||||
|
||||
/** If R*C is much larger or smaller than the current, deletes all previous data
|
||||
and resets to random data. Otherwise re-uses existing memory and just resets
|
||||
R, C, and the row pointers. */
|
||||
void setSize(int newRows, int newCols);
|
||||
|
||||
inline Impl() : elt(NULL), data(NULL), R(0), C(0), dataSize(0) {}
|
||||
|
||||
Impl(const Matrix3& M);
|
||||
|
||||
Impl(const Matrix4& M);
|
||||
|
||||
inline Impl(int r, int c) : elt(NULL), data(NULL), R(0), C(0), dataSize(0) {
|
||||
setSize(r, c);
|
||||
}
|
||||
|
||||
Impl& operator=(const Impl& m);
|
||||
|
||||
inline Impl(const Impl& B) : elt(NULL), data(NULL), R(0), C(0), dataSize(0) {
|
||||
// Use the assignment operator
|
||||
*this = B;
|
||||
}
|
||||
|
||||
void setZero();
|
||||
|
||||
inline void set(int r, int c, T v) {
|
||||
debugAssert(r < R);
|
||||
debugAssert(c < C);
|
||||
elt[r][c] = v;
|
||||
}
|
||||
|
||||
inline const T& get(int r, int c) const {
|
||||
debugAssert(r < R);
|
||||
debugAssert(c < C);
|
||||
return elt[r][c];
|
||||
}
|
||||
|
||||
/** Multiplies this by B and puts the result in out. */
|
||||
void mul(const Impl& B, Impl& out) const;
|
||||
|
||||
/** Ok if out == this or out == B */
|
||||
void add(const Impl& B, Impl& out) const;
|
||||
|
||||
/** Ok if out == this or out == B */
|
||||
void add(T B, Impl& out) const;
|
||||
|
||||
/** Ok if out == this or out == B */
|
||||
void sub(const Impl& B, Impl& out) const;
|
||||
|
||||
/** Ok if out == this or out == B */
|
||||
void sub(T B, Impl& out) const;
|
||||
|
||||
/** B - this */
|
||||
void lsub(T B, Impl& out) const;
|
||||
|
||||
/** Ok if out == this or out == B */
|
||||
void arrayMul(const Impl& B, Impl& out) const;
|
||||
|
||||
/** Ok if out == this or out == B */
|
||||
void mul(T B, Impl& out) const;
|
||||
|
||||
/** Ok if out == this or out == B */
|
||||
void arrayDiv(const Impl& B, Impl& out) const;
|
||||
|
||||
/** Ok if out == this or out == B */
|
||||
void div(T B, Impl& out) const;
|
||||
|
||||
void negate(Impl& out) const;
|
||||
|
||||
/** Slow way of computing an inverse; for reference */
|
||||
void inverseViaAdjoint(Impl& out) const;
|
||||
|
||||
/** Use Gaussian elimination with pivots to solve for the inverse destructively in place. */
|
||||
void inverseInPlaceGaussJordan();
|
||||
|
||||
void adjoint(Impl& out) const;
|
||||
|
||||
/** Matrix of all cofactors */
|
||||
void cofactor(Impl& out) const;
|
||||
|
||||
/**
|
||||
Cofactor [r][c] is defined as C[r][c] = -1 ^(r+c) * det(A[r][c]),
|
||||
where A[r][c] is the (R-1)x(C-1) matrix formed by removing row r and
|
||||
column c from the original matrix.
|
||||
*/
|
||||
T cofactor(int r, int c) const;
|
||||
|
||||
/** Ok if out == this or out == B */
|
||||
void transpose(Impl& out) const;
|
||||
|
||||
T determinant() const;
|
||||
|
||||
/** Determinant computed without the given row and column */
|
||||
T determinant(int r, int c) const;
|
||||
|
||||
void arrayLog(Impl& out) const;
|
||||
|
||||
void arrayExp(Impl& out) const;
|
||||
|
||||
void arraySqrt(Impl& out) const;
|
||||
|
||||
void arrayCos(Impl& out) const;
|
||||
|
||||
void arraySin(Impl& out) const;
|
||||
|
||||
void swapRows(int r0, int r1);
|
||||
|
||||
void swapAndNegateCols(int c0, int c1);
|
||||
|
||||
void mulRow(int r, const T& v);
|
||||
|
||||
void abs(Impl& out) const;
|
||||
|
||||
/** Makes a (R-1)x(C-1) copy of this matrix */
|
||||
void withoutRowAndCol(int excludeRow, int excludeCol, Impl& out) const;
|
||||
|
||||
bool anyNonZero() const;
|
||||
|
||||
bool allNonZero() const;
|
||||
|
||||
void setRow(int r, const T* vals);
|
||||
|
||||
void setCol(int c, const T* vals);
|
||||
};
|
||||
private:
|
||||
|
||||
typedef ReferenceCountedPointer<Impl> ImplRef;
|
||||
|
||||
ImplRef impl;
|
||||
|
||||
inline Matrix(ImplRef i) : impl(i) {}
|
||||
inline Matrix(Impl* i) : impl(ImplRef(i)) {}
|
||||
|
||||
/** Used by SVD */
|
||||
class SortRank {
|
||||
public:
|
||||
T value;
|
||||
int col;
|
||||
|
||||
inline bool operator>(const SortRank& x) const {
|
||||
return x.value > value;
|
||||
}
|
||||
|
||||
inline bool operator<(const SortRank& x) const {
|
||||
return x.value < value;
|
||||
}
|
||||
|
||||
inline bool operator>=(const SortRank& x) const {
|
||||
return x.value >= value;
|
||||
}
|
||||
|
||||
inline bool operator<=(const SortRank& x) const {
|
||||
return x.value <= value;
|
||||
}
|
||||
|
||||
inline bool operator==(const SortRank& x) const {
|
||||
return x.value == value;
|
||||
}
|
||||
|
||||
inline bool operator!=(const SortRank& x) const {
|
||||
return x.value != value;
|
||||
}
|
||||
};
|
||||
|
||||
Matrix vectorPseudoInverse() const;
|
||||
Matrix partitionPseudoInverse() const;
|
||||
Matrix colPartPseudoInverse() const;
|
||||
Matrix rowPartPseudoInverse() const;
|
||||
|
||||
Matrix col2PseudoInverse(const Matrix& B) const;
|
||||
Matrix col3PseudoInverse(const Matrix& B) const;
|
||||
Matrix col4PseudoInverse(const Matrix& B) const;
|
||||
Matrix row2PseudoInverse(const Matrix& B) const;
|
||||
Matrix row3PseudoInverse(const Matrix& B) const;
|
||||
Matrix row4PseudoInverse(const Matrix& B) const;
|
||||
|
||||
public:
|
||||
|
||||
Matrix() : impl(new Impl(0, 0)) {}
|
||||
|
||||
Matrix(const Matrix3& M) : impl(new Impl(M)) {}
|
||||
|
||||
Matrix(const Matrix4& M) : impl(new Impl(M)) {}
|
||||
|
||||
template<class S>
|
||||
static Matrix fromDiagonal(const Array<S>& d) {
|
||||
Matrix D = zero(d.length(), d.length());
|
||||
for (int i = 0; i < d.length(); ++i) {
|
||||
D.set(i, i, d[i]);
|
||||
}
|
||||
return D;
|
||||
}
|
||||
|
||||
static Matrix fromDiagonal(const Matrix& d);
|
||||
|
||||
/** Returns a new matrix that is all zero. */
|
||||
Matrix(int R, int C) : impl(new Impl(R, C)) {
|
||||
impl->setZero();
|
||||
}
|
||||
|
||||
/** Returns a new matrix that is all zero. */
|
||||
static Matrix zero(int R, int C);
|
||||
|
||||
/** Returns a new matrix that is all one. */
|
||||
static Matrix one(int R, int C);
|
||||
|
||||
/** Returns a new identity matrix */
|
||||
static Matrix identity(int N);
|
||||
|
||||
/** Uniformly distributed values between zero and one. */
|
||||
static Matrix random(int R, int C);
|
||||
|
||||
/** The number of rows */
|
||||
inline int rows() const {
|
||||
return impl->R;
|
||||
}
|
||||
|
||||
/** Number of columns */
|
||||
inline int cols() const {
|
||||
return impl->C;
|
||||
}
|
||||
|
||||
/** Generally more efficient than A * B */
|
||||
Matrix& operator*=(const T& B);
|
||||
|
||||
/** Generally more efficient than A / B */
|
||||
Matrix& operator/=(const T& B);
|
||||
|
||||
/** Generally more efficient than A + B */
|
||||
Matrix& operator+=(const T& B);
|
||||
|
||||
/** Generally more efficient than A - B */
|
||||
Matrix& operator-=(const T& B);
|
||||
|
||||
/** No performance advantage over A * B because
|
||||
matrix multiplication requires intermediate
|
||||
storage. */
|
||||
Matrix& operator*=(const Matrix& B);
|
||||
|
||||
/** Generally more efficient than A + B */
|
||||
Matrix& operator+=(const Matrix& B);
|
||||
|
||||
/** Generally more efficient than A - B */
|
||||
Matrix& operator-=(const Matrix& B);
|
||||
|
||||
/** Returns a new matrix that is a subset of this one,
|
||||
from r1:r2 to c1:c2, inclusive.*/
|
||||
Matrix subMatrix(int r1, int r2, int c1, int c2) const;
|
||||
|
||||
/** Matrix multiplication. To perform element-by-element multiplication,
|
||||
see arrayMul. */
|
||||
inline Matrix operator*(const Matrix& B) const {
|
||||
Matrix C(impl->R, B.impl->C);
|
||||
impl->mul(*B.impl, *C.impl);
|
||||
return C;
|
||||
}
|
||||
|
||||
/** See also A *= B, which is more efficient in many cases */
|
||||
inline Matrix operator*(const T& B) const {
|
||||
Matrix C(impl->R, impl->C);
|
||||
impl->mul(B, *C.impl);
|
||||
return C;
|
||||
}
|
||||
|
||||
/** See also A += B, which is more efficient in many cases */
|
||||
inline Matrix operator+(const Matrix& B) const {
|
||||
Matrix C(impl->R, impl->C);
|
||||
impl->add(*B.impl, *C.impl);
|
||||
return C;
|
||||
}
|
||||
|
||||
/** See also A -= B, which is more efficient in many cases */
|
||||
inline Matrix operator-(const Matrix& B) const {
|
||||
Matrix C(impl->R, impl->C);
|
||||
impl->sub(*B.impl, *C.impl);
|
||||
return C;
|
||||
}
|
||||
|
||||
/** See also A += B, which is more efficient in many cases */
|
||||
inline Matrix operator+(const T& v) const {
|
||||
Matrix C(impl->R, impl->C);
|
||||
impl->add(v, *C.impl);
|
||||
return C;
|
||||
}
|
||||
|
||||
/** See also A -= B, which is more efficient in many cases */
|
||||
inline Matrix operator-(const T& v) const {
|
||||
Matrix C(impl->R, impl->C);
|
||||
impl->sub(v, *C.impl);
|
||||
return C;
|
||||
}
|
||||
|
||||
|
||||
Matrix operator>(const T& scalar) const;
|
||||
|
||||
Matrix operator<(const T& scalar) const;
|
||||
|
||||
Matrix operator>=(const T& scalar) const;
|
||||
|
||||
Matrix operator<=(const T& scalar) const;
|
||||
|
||||
Matrix operator==(const T& scalar) const;
|
||||
|
||||
Matrix operator!=(const T& scalar) const;
|
||||
|
||||
/** scalar B - this */
|
||||
inline Matrix lsub(const T& B) const {
|
||||
Matrix C(impl->R, impl->C);
|
||||
impl->lsub(B, *C.impl);
|
||||
return C;
|
||||
}
|
||||
|
||||
inline Matrix arrayMul(const Matrix& B) const {
|
||||
Matrix C(impl->R, impl->C);
|
||||
impl->arrayMul(*B.impl, *C.impl);
|
||||
return C;
|
||||
}
|
||||
|
||||
Matrix3 toMatrix3() const;
|
||||
|
||||
Matrix4 toMatrix4() const;
|
||||
|
||||
Vector2 toVector2() const;
|
||||
|
||||
Vector3 toVector3() const;
|
||||
|
||||
Vector4 toVector4() const;
|
||||
|
||||
/** Mutates this */
|
||||
void arrayMulInPlace(const Matrix& B);
|
||||
|
||||
/** Mutates this */
|
||||
void arrayDivInPlace(const Matrix& B);
|
||||
|
||||
// Declares an array unary method and its explicit-argument counterpart
|
||||
# define DECLARE_METHODS_1(method)\
|
||||
inline Matrix method() const {\
|
||||
Matrix C(impl->R, impl->C);\
|
||||
impl->method(*C.impl);\
|
||||
return C;\
|
||||
}\
|
||||
void method(Matrix& out) const;
|
||||
|
||||
|
||||
DECLARE_METHODS_1(abs)
|
||||
DECLARE_METHODS_1(arrayLog)
|
||||
DECLARE_METHODS_1(arrayExp)
|
||||
DECLARE_METHODS_1(arraySqrt)
|
||||
DECLARE_METHODS_1(arrayCos)
|
||||
DECLARE_METHODS_1(arraySin)
|
||||
DECLARE_METHODS_1(negate)
|
||||
|
||||
# undef DECLARE_METHODS_1
|
||||
|
||||
inline Matrix operator-() const {
|
||||
return negate();
|
||||
}
|
||||
|
||||
/**
|
||||
A<SUP>-1</SUP> computed using the Gauss-Jordan algorithm,
|
||||
for square matrices.
|
||||
Run time is <I>O(R<sup>3</sup>)</I>, where <I>R</i> is the
|
||||
number of rows.
|
||||
*/
|
||||
inline Matrix inverse() const {
|
||||
Impl* A = new Impl(*impl);
|
||||
A->inverseInPlaceGaussJordan();
|
||||
return Matrix(A);
|
||||
}
|
||||
|
||||
inline T determinant() const {
|
||||
return impl->determinant();
|
||||
}
|
||||
|
||||
/**
|
||||
A<SUP>T</SUP>
|
||||
*/
|
||||
inline Matrix transpose() const {
|
||||
Impl* A = new Impl(cols(), rows());
|
||||
impl->transpose(*A);
|
||||
return Matrix(A);
|
||||
}
|
||||
|
||||
/** Transpose in place; more efficient than transpose */
|
||||
void transpose(Matrix& out) const;
|
||||
|
||||
inline Matrix adjoint() const {
|
||||
Impl* A = new Impl(cols(), rows());
|
||||
impl->adjoint(*A);
|
||||
return Matrix(A);
|
||||
}
|
||||
|
||||
/**
|
||||
(A<SUP>T</SUP>A)<SUP>-1</SUP>A<SUP>T</SUP>) computed
|
||||
using SVD.
|
||||
|
||||
@param tolerance Use -1 for automatic tolerance.
|
||||
*/
|
||||
Matrix pseudoInverse(float tolerance = -1) const;
|
||||
|
||||
/** Called from pseudoInverse when the matrix has size > 4 along some dimension.*/
|
||||
Matrix svdPseudoInverse(float tolerance = -1) const;
|
||||
|
||||
/**
|
||||
(A<SUP>T</SUP>A)<SUP>-1</SUP>A<SUP>T</SUP>) computed
|
||||
using Gauss-Jordan elimination.
|
||||
*/
|
||||
inline Matrix gaussJordanPseudoInverse() const {
|
||||
Matrix trans = transpose();
|
||||
return (trans * (*this)).inverse() * trans;
|
||||
}
|
||||
|
||||
/** Singular value decomposition. Factors into three matrices
|
||||
such that @a this = @a U * fromDiagonal(@a d) * @a V.transpose().
|
||||
|
||||
The matrix must have at least as many rows as columns.
|
||||
|
||||
Run time is <I>O(C<sup>2</sup>*R)</I>.
|
||||
|
||||
@param sort If true (default), the singular values
|
||||
are arranged so that D is sorted from largest to smallest.
|
||||
*/
|
||||
void svd(Matrix& U, Array<T>& d, Matrix& V, bool sort = true) const;
|
||||
|
||||
void set(int r, int c, T v);
|
||||
|
||||
void setCol(int c, const Matrix& vec);
|
||||
|
||||
void setRow(int r, const Matrix& vec);
|
||||
|
||||
Matrix col(int c) const;
|
||||
|
||||
Matrix row(int r) const;
|
||||
|
||||
T get(int r, int c) const;
|
||||
|
||||
Vector2int16 size() const {
|
||||
return Vector2int16(rows(), cols());
|
||||
}
|
||||
|
||||
int numElements() const {
|
||||
return rows() * cols();
|
||||
}
|
||||
|
||||
void swapRows(int r0, int r1);
|
||||
|
||||
/** Swaps columns c0 and c1 and negates both */
|
||||
void swapAndNegateCols(int c0, int c1);
|
||||
|
||||
void mulRow(int r, const T& v);
|
||||
|
||||
/** Returns true if any element is non-zero */
|
||||
bool anyNonZero() const;
|
||||
|
||||
/** Returns true if all elements are non-zero */
|
||||
bool allNonZero() const;
|
||||
|
||||
inline bool allZero() const {
|
||||
return !anyNonZero();
|
||||
}
|
||||
|
||||
inline bool anyZero() const {
|
||||
return !allNonZero();
|
||||
}
|
||||
|
||||
/** Serializes in Matlab source format */
|
||||
void serialize(TextOutput& t) const;
|
||||
|
||||
std::string toString(const std::string& name) const;
|
||||
|
||||
std::string toString() const {
|
||||
static const std::string name = "";
|
||||
return toString(name);
|
||||
}
|
||||
|
||||
/** 2-norm squared: sum(squares). (i.e., dot product with itself) */
|
||||
double normSquared() const;
|
||||
|
||||
/** 2-norm (sqrt(sum(squares)) */
|
||||
double norm() const;
|
||||
|
||||
/**
|
||||
Low-level SVD functionality. Useful for applications that do not want
|
||||
to construct a Matrix but need to perform the SVD operation.
|
||||
|
||||
this = U * D * V'
|
||||
|
||||
Assumes that rows >= cols
|
||||
|
||||
@return NULL on success, a string describing the error on failure.
|
||||
@param U rows x cols matrix to be decomposed, gets overwritten with U, a rows x cols matrix with orthogonal columns.
|
||||
@param D vector of singular values of a (diagonal of the D matrix). Length cols.
|
||||
@param V returns the right orthonormal transformation matrix, size cols x cols
|
||||
|
||||
@cite Based on Dianne Cook's implementation, which is adapted from
|
||||
svdecomp.c in XLISP-STAT 2.1, which is code from Numerical Recipes
|
||||
adapted by Luke Tierney and David Betz. The Numerical Recipes code
|
||||
is adapted from Forsythe et al, who based their code on Golub and
|
||||
Reinsch's original implementation.
|
||||
*/
|
||||
static const char* svdCore(float** U, int rows, int cols, float* D, float** V);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
inline G3D::Matrix operator-(const G3D::Matrix::T& v, const G3D::Matrix& M) {
|
||||
return M.lsub(v);
|
||||
}
|
||||
|
||||
inline G3D::Matrix operator*(const G3D::Matrix::T& v, const G3D::Matrix& M) {
|
||||
return M * v;
|
||||
}
|
||||
|
||||
inline G3D::Matrix operator+(const G3D::Matrix::T& v, const G3D::Matrix& M) {
|
||||
return M + v;
|
||||
}
|
||||
|
||||
inline G3D::Matrix abs(const G3D::Matrix& M) {
|
||||
return M.abs();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
69
dep/include/g3dlite/G3D/Matrix2.h
Normal file
69
dep/include/g3dlite/G3D/Matrix2.h
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
#ifndef G3D_MATRIX2_H
|
||||
#define G3D_MATRIX2_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Vector2.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/** @beta */
|
||||
class Matrix2 {
|
||||
private:
|
||||
|
||||
float data[2][2];
|
||||
|
||||
public:
|
||||
|
||||
inline Matrix2() {
|
||||
data[0][0] = 1.0f; data[0][1] = 0.0f;
|
||||
data[1][0] = 0.0f; data[1][1] = 1.0f;
|
||||
}
|
||||
|
||||
inline Matrix2(float v00, float v01, float v10, float v11) {
|
||||
data[0][0] = v00; data[0][1] = v01;
|
||||
data[1][0] = v10; data[1][1] = v11;
|
||||
}
|
||||
|
||||
inline Vector2 operator*(const Vector2& v) const {
|
||||
return Vector2(data[0][0] * v[0] + data[0][1] * v[1],
|
||||
data[1][0] * v[0] + data[1][1] * v[1]);
|
||||
}
|
||||
|
||||
inline Matrix2 inverse() const {
|
||||
return Matrix2(data[0][0], data[1][0],
|
||||
data[0][1], data[1][1]) * (1.0f / determinant());
|
||||
}
|
||||
|
||||
inline Matrix2 transpose() const {
|
||||
return Matrix2(data[0][0], data[1][0],
|
||||
data[0][1], data[1][1]);
|
||||
}
|
||||
|
||||
inline float determinant() const {
|
||||
return data[0][0] * data[1][1] - data[0][1] * data[1][0];
|
||||
}
|
||||
|
||||
inline Matrix2 operator*(float f) const {
|
||||
return Matrix2(data[0][0] * f, data[0][1] * f,
|
||||
data[1][0] * f, data[1][1] * f);
|
||||
}
|
||||
|
||||
inline Matrix2 operator/(float f) const {
|
||||
return Matrix2(data[0][0] / f, data[0][1] / f,
|
||||
data[1][0] / f, data[1][1] / f);
|
||||
}
|
||||
|
||||
inline float* operator[](int i) {
|
||||
debugAssert(i >= 0 && i <= 2);
|
||||
return data[i];
|
||||
}
|
||||
|
||||
inline const float* operator[](int i) const {
|
||||
debugAssert(i >= 0 && i <= 1);
|
||||
return data[i];
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
3x3 matrix class
|
||||
|
||||
@maintainer Morgan McGuire, matrix@graphics3d.com
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@cite Portions based on Dave Eberly's Magic Software Library at <A HREF="http://www.magic-software.com">http://www.magic-software.com</A>
|
||||
|
||||
|
|
@ -11,16 +11,26 @@
|
|||
@edited 2006-04-05
|
||||
*/
|
||||
|
||||
#ifndef G3D_MATRIX3_H
|
||||
#define G3D_MATRIX3_H
|
||||
#ifndef G3D_Matrix3_h
|
||||
#define G3D_Matrix3_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/System.h"
|
||||
#include "G3D/Vector3.h"
|
||||
#include "G3D/Vector4.h"
|
||||
#include "G3D/debugAssert.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace G3D {
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Turn off "conditional expression is constant" warning; MSVC generates this
|
||||
// for debug assertions in inlined methods.
|
||||
# pragma warning (disable : 4127)
|
||||
#endif
|
||||
|
||||
class Any;
|
||||
|
||||
/**
|
||||
3x3 matrix. Do not subclass.
|
||||
*/
|
||||
|
|
@ -37,23 +47,33 @@ private:
|
|||
|
||||
public:
|
||||
|
||||
Matrix3(const Any& any);
|
||||
|
||||
operator Any() const;
|
||||
|
||||
/** Initial values are undefined for performance. See also
|
||||
Matrix3::zero(), Matrix3::identity(), Matrix3::fromAxisAngle, etc.*/
|
||||
inline Matrix3() {}
|
||||
|
||||
Matrix3 (class BinaryInput& b);
|
||||
Matrix3 (const float aafEntry[3][3]);
|
||||
Matrix3 (const Matrix3& rkMatrix);
|
||||
Matrix3 (float fEntry00, float fEntry01, float fEntry02,
|
||||
float fEntry10, float fEntry11, float fEntry12,
|
||||
float fEntry20, float fEntry21, float fEntry22);
|
||||
|
||||
bool fuzzyEq(const Matrix3& b) const;
|
||||
bool fuzzyEq(const Matrix3& b) const;
|
||||
|
||||
/** Constructs a matrix from a quaternion.
|
||||
@cite Graphics Gems II, p. 351--354
|
||||
@cite Implementation from Watt and Watt, pg 362*/
|
||||
Matrix3(const class Quat& q);
|
||||
|
||||
void serialize(class BinaryOutput& b) const;
|
||||
void deserialize(class BinaryInput& b);
|
||||
|
||||
/** Returns true if column(0).cross(column(1)).dot(column(2)) > 0. */
|
||||
bool isRightHanded() const;
|
||||
|
||||
/**
|
||||
Sets all elements.
|
||||
|
|
@ -84,15 +104,16 @@ public:
|
|||
inline operator const float* () const{
|
||||
return (const float*)&elt[0][0];
|
||||
}
|
||||
|
||||
Vector3 column(int c) const;
|
||||
const Vector3& row(int r) const;
|
||||
|
||||
Vector3 getColumn (int iCol) const;
|
||||
Vector3 getRow (int iRow) const;
|
||||
void setColumn(int iCol, const Vector3 &vector);
|
||||
void setRow(int iRow, const Vector3 &vector);
|
||||
|
||||
// assignment and comparison
|
||||
inline Matrix3& operator= (const Matrix3& rkMatrix) {
|
||||
System::memcpy(elt, rkMatrix.elt, 9 * sizeof(float));
|
||||
memcpy(elt, rkMatrix.elt, 9 * sizeof(float));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -143,6 +164,10 @@ public:
|
|||
friend Matrix3 operator* (float fScalar, const Matrix3& rkMatrix);
|
||||
friend Matrix3 operator* (int fScalar, const Matrix3& rkMatrix);
|
||||
|
||||
Matrix3& operator*= (float k);
|
||||
Matrix3& operator/= (float k);
|
||||
|
||||
|
||||
private:
|
||||
/** Multiplication where out != A and out != B */
|
||||
static void _mul(const Matrix3& A, const Matrix3& B, Matrix3& out);
|
||||
|
|
@ -202,11 +227,46 @@ public:
|
|||
void qDUDecomposition (Matrix3& rkQ, Vector3& rkD,
|
||||
Vector3& rkU) const;
|
||||
|
||||
/**
|
||||
Polar decomposition of a matrix. Based on pseudocode from Nicholas J
|
||||
Higham, "Computing the Polar Decomposition -- with Applications Siam
|
||||
Journal of Science and Statistical Computing, Vol 7, No. 4, October
|
||||
1986.
|
||||
|
||||
Decomposes A into R*S, where R is orthogonal and S is symmetric.
|
||||
|
||||
Ken Shoemake's "Matrix animation and polar decomposition"
|
||||
in Proceedings of the conference on Graphics interface '92
|
||||
seems to be better known in the world of graphics, but Higham's version
|
||||
uses a scaling constant that can lead to faster convergence than
|
||||
Shoemake's when the initial matrix is far from orthogonal.
|
||||
*/
|
||||
void polarDecomposition(Matrix3 &R, Matrix3 &S) const;
|
||||
|
||||
/**
|
||||
* Matrix norms.
|
||||
*/
|
||||
float spectralNorm () const;
|
||||
|
||||
float squaredFrobeniusNorm() const;
|
||||
|
||||
float frobeniusNorm() const;
|
||||
|
||||
float l1Norm() const;
|
||||
|
||||
float lInfNorm() const;
|
||||
|
||||
float diffOneNorm(const Matrix3 &y) const;
|
||||
|
||||
/** matrix must be orthonormal */
|
||||
void toAxisAngle(Vector3& rkAxis, float& rfRadians) const;
|
||||
|
||||
static Matrix3 fromDiagonal(const Vector3& d) {
|
||||
return Matrix3(d.x, 0, 0,
|
||||
0, d.y, 0,
|
||||
0, 0, d.z);
|
||||
}
|
||||
|
||||
static Matrix3 fromAxisAngle(const Vector3& rkAxis, float fRadians);
|
||||
|
||||
/**
|
||||
|
|
@ -239,7 +299,7 @@ public:
|
|||
|
||||
static void tensorProduct (const Vector3& rkU, const Vector3& rkV,
|
||||
Matrix3& rkProduct);
|
||||
std::string toString() const;
|
||||
std::string toString() const;
|
||||
|
||||
static const float EPSILON;
|
||||
|
||||
|
|
@ -252,7 +312,7 @@ public:
|
|||
// "You might be tempted to write [...] them as inline functions
|
||||
// inside their respective header files, but this is something you
|
||||
// must definitely not do. An inline function can be duplicated
|
||||
// in every file in which it appears – and this duplication
|
||||
// in every file in which it appears œóõ½ and this duplication
|
||||
// includes the static object definition. Because inline functions
|
||||
// automatically default to internal linkage, this would result in
|
||||
// having multiple static objects across the various translation
|
||||
|
|
@ -264,13 +324,8 @@ public:
|
|||
static const Matrix3& zero();
|
||||
static const Matrix3& identity();
|
||||
|
||||
// Deprecated.
|
||||
/** @deprecated Use Matrix3::zero() */
|
||||
static const Matrix3 ZERO;
|
||||
/** @deprecated Use Matrix3::identity() */
|
||||
static const Matrix3 IDENTITY;
|
||||
|
||||
protected:
|
||||
|
||||
// support for eigensolver
|
||||
void tridiagonal (float afDiag[3], float afSubDiag[3]);
|
||||
bool qLAlgorithm (float afDiag[3], float afSubDiag[3]);
|
||||
|
|
|
|||
249
dep/include/g3dlite/G3D/Matrix4.h
Normal file
249
dep/include/g3dlite/G3D/Matrix4.h
Normal file
|
|
@ -0,0 +1,249 @@
|
|||
/**
|
||||
@file Matrix4.h
|
||||
|
||||
4x4 matrix class
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2003-10-02
|
||||
@edited 2009-10-20
|
||||
*/
|
||||
|
||||
#ifndef G3D_Matrix4_h
|
||||
#define G3D_Matrix4_h
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Disable conditional expression is constant, which occurs incorrectly on inlined functions
|
||||
# pragma warning (push)
|
||||
# pragma warning( disable : 4127 )
|
||||
#endif
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/debugAssert.h"
|
||||
#include "G3D/Matrix3.h"
|
||||
#include "G3D/Vector3.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
class Any;
|
||||
|
||||
/**
|
||||
A 4x4 matrix.
|
||||
|
||||
See also G3D::CoordinateFrame, G3D::Matrix3, G3D::Quat
|
||||
*/
|
||||
class Matrix4 {
|
||||
private:
|
||||
|
||||
float elt[4][4];
|
||||
|
||||
/**
|
||||
Computes the determinant of the 3x3 matrix that lacks excludeRow
|
||||
and excludeCol.
|
||||
*/
|
||||
float subDeterminant(int excludeRow, int excludeCol) const;
|
||||
|
||||
// Hidden operators
|
||||
bool operator<(const Matrix4&) const;
|
||||
bool operator>(const Matrix4&) const;
|
||||
bool operator<=(const Matrix4&) const;
|
||||
bool operator>=(const Matrix4&) const;
|
||||
|
||||
public:
|
||||
/** Must be of the form: <code>Matrix4(#, #, # .... #)</code>*/
|
||||
Matrix4(const Any& any);
|
||||
|
||||
operator Any() const;
|
||||
|
||||
Matrix4(
|
||||
float r1c1, float r1c2, float r1c3, float r1c4,
|
||||
float r2c1, float r2c2, float r2c3, float r2c4,
|
||||
float r3c1, float r3c2, float r3c3, float r3c4,
|
||||
float r4c1, float r4c2, float r4c3, float r4c4);
|
||||
|
||||
/**
|
||||
init should be <B>row major</B>.
|
||||
*/
|
||||
Matrix4(const float* init);
|
||||
|
||||
/**
|
||||
a is the upper left 3x3 submatrix and b is the upper right 3x1 submatrix. The last row of the created matrix is (0,0,0,1).
|
||||
*/
|
||||
Matrix4(const class Matrix3& upper3x3, const class Vector3& lastCol = Vector3::zero());
|
||||
|
||||
Matrix4(const class CoordinateFrame& c);
|
||||
|
||||
Matrix4(const double* init);
|
||||
|
||||
Matrix4();
|
||||
|
||||
/** Produces an RT transformation that nearly matches this Matrix4.
|
||||
Because a Matrix4 may not be precisely a rotation and translation,
|
||||
this may introduce error. */
|
||||
class CoordinateFrame approxCoordinateFrame() const;
|
||||
|
||||
// Special values.
|
||||
// Intentionally not inlined: see Matrix3::identity() for details.
|
||||
static const Matrix4& identity();
|
||||
static const Matrix4& zero();
|
||||
|
||||
/** If this is a perspective projection matrix created by
|
||||
Matrix4::perspectiveProjection, extract its parameters. */
|
||||
void getPerspectiveProjectionParameters
|
||||
(float& left,
|
||||
float& right,
|
||||
float& bottom,
|
||||
float& top,
|
||||
float& nearval,
|
||||
float& farval,
|
||||
float updirection = -1.0f) const;
|
||||
|
||||
inline float* operator[](int r) {
|
||||
debugAssert(r >= 0);
|
||||
debugAssert(r < 4);
|
||||
return (float*)&elt[r];
|
||||
}
|
||||
|
||||
inline const float* operator[](int r) const {
|
||||
debugAssert(r >= 0);
|
||||
debugAssert(r < 4);
|
||||
return (const float*)&elt[r];
|
||||
}
|
||||
|
||||
inline operator float* () {
|
||||
return (float*)&elt[0][0];
|
||||
}
|
||||
|
||||
inline operator const float* () const {
|
||||
return (const float*)&elt[0][0];
|
||||
}
|
||||
|
||||
Matrix4 operator*(const Matrix4& other) const;
|
||||
|
||||
class Matrix3 upper3x3() const;
|
||||
|
||||
/** Homogeneous multiplication. Let k = M * [v w]^T. result = k.xyz() / k.w */
|
||||
class Vector3 homoMul(const class Vector3& v, float w) const;
|
||||
|
||||
/**
|
||||
Constructs an orthogonal projection matrix from the given parameters.
|
||||
Near and far are the <b>NEGATIVE</b> of the near and far plane Z values
|
||||
(to follow OpenGL conventions).
|
||||
|
||||
\param upDirection Use -1.0 for 2D Y increasing downwards (the G3D 8.x default convention),
|
||||
1.0 for 2D Y increasing upwards (the G3D 7.x default and OpenGL convention)
|
||||
*/
|
||||
static Matrix4 orthogonalProjection(
|
||||
float left,
|
||||
float right,
|
||||
float bottom,
|
||||
float top,
|
||||
float nearval,
|
||||
float farval,
|
||||
float upDirection = -1.0f);
|
||||
|
||||
|
||||
/** \param upDirection Use -1.0 for 2D Y increasing downwards (the G3D 8.x default convention),
|
||||
1.0 for 2D Y increasing upwards (the G3D 7.x default and OpenGL convention)
|
||||
*/
|
||||
static Matrix4 orthogonalProjection(
|
||||
const class Rect2D& rect,
|
||||
float nearval,
|
||||
float farval,
|
||||
float upDirection = -1.0f);
|
||||
|
||||
/** \param upDirection Use -1.0 for 2D Y increasing downwards (the G3D 8.x default convention),
|
||||
1.0 for 2D Y increasing upwards (the G3D 7.x default and OpenGL convention)
|
||||
*/
|
||||
static Matrix4 perspectiveProjection(
|
||||
float left,
|
||||
float right,
|
||||
float bottom,
|
||||
float top,
|
||||
float nearval,
|
||||
float farval,
|
||||
float upDirection = -1.0f);
|
||||
|
||||
void setRow(int r, const class Vector4& v);
|
||||
void setColumn(int c, const Vector4& v);
|
||||
|
||||
const Vector4& row(int r) const;
|
||||
Vector4 column(int c) const;
|
||||
|
||||
Matrix4 operator*(const float s) const;
|
||||
Vector4 operator*(const Vector4& vector) const;
|
||||
|
||||
Matrix4 transpose() const;
|
||||
|
||||
bool operator!=(const Matrix4& other) const;
|
||||
bool operator==(const Matrix4& other) const;
|
||||
|
||||
float determinant() const;
|
||||
Matrix4 inverse() const;
|
||||
|
||||
/**
|
||||
Transpose of the cofactor matrix (used in computing the inverse).
|
||||
Note: This is in fact only one type of adjoint. More generally,
|
||||
an adjoint of a matrix is any mapping of a matrix which possesses
|
||||
certain properties. This returns the so-called adjugate
|
||||
or classical adjoint.
|
||||
*/
|
||||
Matrix4 adjoint() const;
|
||||
Matrix4 cofactor() const;
|
||||
|
||||
/** Serializes row-major */
|
||||
void serialize(class BinaryOutput& b) const;
|
||||
void deserialize(class BinaryInput& b);
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
/** 3D scale matrix */
|
||||
inline static Matrix4 scale(const Vector3& v) {
|
||||
return Matrix4(v.x, 0, 0, 0,
|
||||
0, v.y, 0, 0,
|
||||
0, 0, v.z, 0,
|
||||
0, 0, 0, 1);
|
||||
}
|
||||
|
||||
/** 3D scale matrix */
|
||||
inline static Matrix4 scale(float x, float y, float z) {
|
||||
return scale(Vector3(x, y, z));
|
||||
}
|
||||
|
||||
/** 3D scale matrix */
|
||||
inline static Matrix4 scale(float s) {
|
||||
return scale(s,s,s);
|
||||
}
|
||||
|
||||
/** 3D translation matrix */
|
||||
inline static Matrix4 translation(const Vector3& v) {
|
||||
return Matrix4(Matrix3::identity(), v);
|
||||
}
|
||||
|
||||
inline static Matrix4 translation(float x, float y, float z) {
|
||||
return Matrix4(Matrix3::identity(), Vector3(x, y, z));
|
||||
}
|
||||
|
||||
/** Create a rotation matrix that rotates \a deg degrees around the Y axis */
|
||||
inline static Matrix4 yawDegrees(float deg) {
|
||||
return Matrix4(Matrix3::fromAxisAngle(Vector3::unitY(), toRadians(deg)));
|
||||
}
|
||||
|
||||
inline static Matrix4 pitchDegrees(float deg) {
|
||||
return Matrix4(Matrix3::fromAxisAngle(Vector3::unitX(), toRadians(deg)));
|
||||
}
|
||||
|
||||
inline static Matrix4 rollDegrees(float deg) {
|
||||
return Matrix4(Matrix3::fromAxisAngle(Vector3::unitZ(), toRadians(deg)));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning (pop)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
93
dep/include/g3dlite/G3D/MemoryManager.h
Normal file
93
dep/include/g3dlite/G3D/MemoryManager.h
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
/**
|
||||
@file MemoryManager.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
@created 2009-04-20
|
||||
@edited 2009-04-20
|
||||
|
||||
Copyright 2000-2009, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
#ifndef G3D_MemoryManager_h
|
||||
#define G3D_MemoryManager_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/ReferenceCount.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
Abstraction of memory management.
|
||||
Default implementation uses G3D::System::malloc and is threadsafe.
|
||||
|
||||
\sa CRTMemoryManager, AlignedMemoryManager, AreaMemoryManager */
|
||||
class MemoryManager : public ReferenceCountedObject {
|
||||
protected:
|
||||
|
||||
MemoryManager();
|
||||
|
||||
public:
|
||||
|
||||
typedef ReferenceCountedPointer<class MemoryManager> Ref;
|
||||
|
||||
/** Return a pointer to \a s bytes of memory that are unused by
|
||||
the rest of the program. The contents of the memory are
|
||||
undefined */
|
||||
virtual void* alloc(size_t s);
|
||||
|
||||
/** Invoke to declare that this memory will no longer be used by
|
||||
the program. The memory manager is not required to actually
|
||||
reuse or release this memory. */
|
||||
virtual void free(void* ptr);
|
||||
|
||||
/** Returns true if this memory manager is threadsafe (i.e., alloc
|
||||
and free can be called asychronously) */
|
||||
virtual bool isThreadsafe() const;
|
||||
|
||||
/** Return the instance. There's only one instance of the default
|
||||
MemoryManager; it is cached after the first creation. */
|
||||
static MemoryManager::Ref create();
|
||||
};
|
||||
|
||||
/**
|
||||
Allocates memory on 16-byte boundaries.
|
||||
\sa MemoryManager, CRTMemoryManager, AreaMemoryManager */
|
||||
class AlignedMemoryManager : public MemoryManager {
|
||||
protected:
|
||||
|
||||
AlignedMemoryManager();
|
||||
|
||||
public:
|
||||
|
||||
typedef ReferenceCountedPointer<class AlignedMemoryManager> Ref;
|
||||
|
||||
|
||||
virtual void* alloc(size_t s);
|
||||
|
||||
virtual void free(void* ptr);
|
||||
|
||||
virtual bool isThreadsafe() const;
|
||||
|
||||
static AlignedMemoryManager::Ref create();
|
||||
};
|
||||
|
||||
|
||||
/** MemoryManager implemented using the C runtime. */
|
||||
class CRTMemoryManager : public MemoryManager {
|
||||
protected:
|
||||
CRTMemoryManager();
|
||||
|
||||
public:
|
||||
typedef ReferenceCountedPointer<class MemoryManager> Ref;
|
||||
virtual void* alloc(size_t s);
|
||||
virtual void free(void* ptr);
|
||||
virtual bool isThreadsafe() const;
|
||||
|
||||
/** There's only one instance of this memory manager; it is
|
||||
cached after the first creation. */
|
||||
static CRTMemoryManager::Ref create();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
683
dep/include/g3dlite/G3D/MeshAlg.h
Normal file
683
dep/include/g3dlite/G3D/MeshAlg.h
Normal file
|
|
@ -0,0 +1,683 @@
|
|||
/**
|
||||
@file MeshAlg.h
|
||||
|
||||
Indexed Mesh algorithms.
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2003-09-14
|
||||
@edited 2010-01-18
|
||||
*/
|
||||
|
||||
#ifndef G3D_MeshAlg_h
|
||||
#define G3D_MeshAlg_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Array.h"
|
||||
#include "G3D/Vector3.h"
|
||||
#include "G3D/CoordinateFrame.h"
|
||||
#include "G3D/SmallArray.h"
|
||||
#include "G3D/constants.h"
|
||||
#include "G3D/Image1.h"
|
||||
|
||||
#ifdef G3D_WIN32
|
||||
// Turn off "conditional expression is constant" warning; MSVC generates this
|
||||
// for debug assertions in inlined methods.
|
||||
#pragma warning (disable : 4127)
|
||||
#endif
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
Indexed <B>mesh alg</B>orithms. You have to build your own mesh class.
|
||||
<P>
|
||||
No mesh class is provided with G3D because there isn't an "ideal"
|
||||
mesh format-- one application needs keyframed animation, another
|
||||
skeletal animation, a third texture coordinates, a fourth
|
||||
cannot precompute information, etc. Instead of compromising, this
|
||||
class implements the hard parts of mesh computation and you can write
|
||||
your own ideal mesh class on top of it.
|
||||
|
||||
\sa G3D::ArticulatedModel, G3D::IFSModel
|
||||
*/
|
||||
class MeshAlg {
|
||||
public:
|
||||
|
||||
/** \deprecated */
|
||||
typedef PrimitiveType Primitive;
|
||||
|
||||
/** Adjacency information for a vertex.
|
||||
Does not contain the vertex position or normal,
|
||||
which are stored in the MeshAlg::Geometry object.
|
||||
<CODE>Vertex</CODE>s must be stored in an array
|
||||
parallel to (indexed in the same way as)
|
||||
MeshAlg::Geometry::vertexArray.
|
||||
*/
|
||||
class Vertex {
|
||||
public:
|
||||
Vertex() {}
|
||||
|
||||
/**
|
||||
Array of edges adjacent to this vertex.
|
||||
Let e = edgeIndex[i].
|
||||
edge[(e >= 0) ? e : ~e].vertexIndex[0] == this
|
||||
vertex index.
|
||||
|
||||
Edges may be listed multiple times if they are
|
||||
degenerate.
|
||||
*/
|
||||
SmallArray<int, 6> edgeIndex;
|
||||
|
||||
/**
|
||||
Returns true if e or ~e is in the edgeIndex list.
|
||||
*/
|
||||
inline bool inEdge(int e) const {
|
||||
return edgeIndex.contains(~e) || edgeIndex.contains(e);
|
||||
}
|
||||
|
||||
/**
|
||||
Array of faces containing this vertex. Faces
|
||||
may be listed multiple times if they are degenerate.
|
||||
*/
|
||||
SmallArray<int, 6> faceIndex;
|
||||
|
||||
inline bool inFace(int f) const {
|
||||
debugAssert(f >= 0);
|
||||
return faceIndex.contains(f);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Oriented, indexed triangle.
|
||||
*/
|
||||
class Face {
|
||||
public:
|
||||
Face();
|
||||
|
||||
/**
|
||||
Used by Edge::faceIndex to indicate a missing face.
|
||||
This is a large negative value.
|
||||
*/
|
||||
static const int NONE;
|
||||
|
||||
|
||||
/**
|
||||
Vertices in the face in counter-clockwise order.
|
||||
Degenerate faces may include the same vertex multiple times.
|
||||
*/
|
||||
int vertexIndex[3];
|
||||
|
||||
inline bool containsVertex(int v) const {
|
||||
return contains(vertexIndex, 3, v);
|
||||
}
|
||||
|
||||
/**
|
||||
Edge indices in counter-clockwise order. Edges are
|
||||
undirected, so it is important to know which way
|
||||
each edge is pointing in a face. This is encoded
|
||||
using negative indices.
|
||||
|
||||
If <CODE>edgeIndex[i] >= 0</CODE> then this face
|
||||
contains the directed edge
|
||||
between vertex indices
|
||||
<CODE>edgeArray[face.edgeIndex[i]].vertexIndex[0]</CODE>
|
||||
and
|
||||
<CODE>edgeArray[face.edgeIndex[i]].vertexIndex[1]</CODE>.
|
||||
|
||||
If <CODE>edgeIndex[i] < 0</CODE> then
|
||||
<CODE>~edgeIndex[i]</CODE> (i.e. the two's
|
||||
complement of) is used and this face contains the directed
|
||||
edge between vertex indices
|
||||
<CODE>edgeArray[~face.edgeIndex[i]].vertexIndex[0]</CODE>
|
||||
and
|
||||
<CODE>edgeArray[~face.edgeIndex[i]].vertexIndex[1]</CODE>.
|
||||
|
||||
Degenerate faces may include the same edge multiple times.
|
||||
*/
|
||||
// Temporarily takes on the value Face::NONE during adjacency
|
||||
// computation to indicate an edge that has not yet been assigned.
|
||||
int edgeIndex[3];
|
||||
|
||||
inline bool containsEdge(int e) const {
|
||||
if (e < 0) {
|
||||
e = ~e;
|
||||
}
|
||||
return contains(edgeIndex, 3, e) || contains(edgeIndex, 3, ~e);
|
||||
}
|
||||
|
||||
/** Contains the forward edge e if e >= 0 and the backward edge
|
||||
~e otherwise. */
|
||||
inline bool containsDirectedEdge(int e) const {
|
||||
return contains(edgeIndex, 3, e);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** Oriented, indexed edge */
|
||||
class Edge {
|
||||
public:
|
||||
Edge();
|
||||
|
||||
/** Degenerate edges may include the same vertex times. */
|
||||
int vertexIndex[2];
|
||||
|
||||
inline bool containsVertex(int v) const {
|
||||
return contains(vertexIndex, 2, v);
|
||||
}
|
||||
|
||||
/**
|
||||
The edge is directed <B>forward</B> in face 0
|
||||
<B>backward</B> in face 1. Face index of MeshAlg::Face::NONE
|
||||
indicates a boundary (a.k.a. crack, broken) edge.
|
||||
*/
|
||||
int faceIndex[2];
|
||||
|
||||
/** Returns true if f is contained in the faceIndex array in either slot.
|
||||
To see if it is forward in that face, just check edge.faceIndex[0] == f.*/
|
||||
inline bool inFace(int f) const {
|
||||
return contains(faceIndex, 2, f);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns true if either faceIndex is NONE.
|
||||
*/
|
||||
inline bool boundary() const {
|
||||
return (faceIndex[0] == Face::NONE) ||
|
||||
(faceIndex[1] == Face::NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the reversed edge.
|
||||
*/
|
||||
inline Edge reverse() const {
|
||||
Edge e;
|
||||
e.vertexIndex[0] = vertexIndex[1];
|
||||
e.vertexIndex[1] = vertexIndex[0];
|
||||
e.faceIndex[0] = faceIndex[1];
|
||||
e.faceIndex[1] = faceIndex[0];
|
||||
return e;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Convenient for passing around the per-vertex data that changes under
|
||||
animation. The faces and edges are needed to interpret
|
||||
these values.
|
||||
*/
|
||||
class Geometry {
|
||||
public:
|
||||
/** Vertex positions */
|
||||
Array<Vector3> vertexArray;
|
||||
|
||||
/** Vertex normals */
|
||||
Array<Vector3> normalArray;
|
||||
|
||||
/**
|
||||
Assignment is optimized using SSE.
|
||||
*/
|
||||
Geometry& operator=(const Geometry& src);
|
||||
|
||||
void clear() {
|
||||
vertexArray.clear();
|
||||
normalArray.clear();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
Given a set of vertices and a set of indices for traversing them
|
||||
to create triangles, computes other mesh properties.
|
||||
|
||||
<B>Colocated vertices are treated as separate.</B> To have
|
||||
colocated vertices collapsed (necessary for many algorithms,
|
||||
like shadowing), weld the mesh before computing adjacency.
|
||||
|
||||
<I>Recent change: In version 6.00, colocated vertices were automatically
|
||||
welded by this routine and degenerate faces and edges were removed. That
|
||||
is no longer the case.</I>
|
||||
|
||||
Where two faces meet, there are two opposite directed edges. These
|
||||
are collapsed into a single bidirectional edge in the edgeArray.
|
||||
If four faces meet exactly at the same edge, that edge will appear
|
||||
twice in the array, and so on. If an edge is a boundary of the mesh
|
||||
(i.e. if the edge has only one adjacent face) it will appear in the
|
||||
array with one face index set to MeshAlg::Face::NONE.
|
||||
|
||||
@param vertexGeometry %Vertex positions to use when deciding colocation.
|
||||
@param indexArray Order to traverse vertices to make triangles
|
||||
@param faceArray <I>Output</I>
|
||||
@param edgeArray <I>Output</I>. Sorted so that boundary edges are at the end of the array.
|
||||
@param vertexArray <I>Output</I>
|
||||
*/
|
||||
static void computeAdjacency(
|
||||
const Array<Vector3>& vertexGeometry,
|
||||
const Array<int>& indexArray,
|
||||
Array<Face>& faceArray,
|
||||
Array<Edge>& edgeArray,
|
||||
Array<Vertex>& vertexArray);
|
||||
|
||||
/**
|
||||
@deprecated Use the other version of computeAdjacency, which takes Array<Vertex>.
|
||||
@param facesAdjacentToVertex <I>Output</I> adjacentFaceArray[v] is an array of
|
||||
indices for faces touching vertex index v
|
||||
*/
|
||||
static void computeAdjacency(
|
||||
const Array<Vector3>& vertexArray,
|
||||
const Array<int>& indexArray,
|
||||
Array<Face>& faceArray,
|
||||
Array<Edge>& edgeArray,
|
||||
Array< Array<int> >& facesAdjacentToVertex);
|
||||
|
||||
/**
|
||||
Computes some basic mesh statistics including: min, max mean and median,
|
||||
edge lengths; and min, mean, median, and max face area.
|
||||
|
||||
@param vertexArray %Vertex positions to use when deciding colocation.
|
||||
@param indexArray Order to traverse vertices to make triangles
|
||||
@param minEdgeLength Minimum edge length
|
||||
@param meanEdgeLength Mean edge length
|
||||
@param medianEdgeLength Median edge length
|
||||
@param maxEdgeLength Max edge length
|
||||
@param minFaceArea Minimum face area
|
||||
@param meanFaceArea Mean face area
|
||||
@param medianFaceArea Median face area
|
||||
@param maxFaceArea Max face area
|
||||
*/
|
||||
static void computeAreaStatistics(
|
||||
const Array<Vector3>& vertexArray,
|
||||
const Array<int>& indexArray,
|
||||
double& minEdgeLength,
|
||||
double& meanEdgeLength,
|
||||
double& medianEdgeLength,
|
||||
double& maxEdgeLength,
|
||||
double& minFaceArea,
|
||||
double& meanFaceArea,
|
||||
double& medianFaceArea,
|
||||
double& maxFaceArea);
|
||||
|
||||
private:
|
||||
|
||||
/** Helper for weldAdjacency */
|
||||
static void weldBoundaryEdges(
|
||||
Array<Face>& faceArray,
|
||||
Array<Edge>& edgeArray,
|
||||
Array<Vertex>& vertexArray);
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
Computes tangent and binormal vectors,
|
||||
which provide a (mostly) consistent
|
||||
parameterization over the surface for
|
||||
effects like bump mapping. In the resulting coordinate frame,
|
||||
T = x (varies with texture s coordinate), B = y (varies with negative texture t coordinate),
|
||||
and N = z for a right-handed coordinate frame. If a billboard is vertical on the screen
|
||||
in view of the camera, the tangent space matches the camera's coordinate frame.
|
||||
|
||||
The vertex, texCoord, tangent, and binormal
|
||||
arrays are parallel arrays.
|
||||
|
||||
The resulting tangent and binormal might not be exactly
|
||||
perpendicular to each other. They are guaranteed to
|
||||
be perpendicular to the normal.
|
||||
|
||||
@cite Max McGuire
|
||||
*/
|
||||
static void computeTangentSpaceBasis(
|
||||
const Array<Vector3>& vertexArray,
|
||||
const Array<Vector2>& texCoordArray,
|
||||
const Array<Vector3>& vertexNormalArray,
|
||||
const Array<Face>& faceArray,
|
||||
Array<Vector3>& tangent,
|
||||
Array<Vector3>& binormal);
|
||||
|
||||
/** @deprecated */
|
||||
static void computeNormals(
|
||||
const Array<Vector3>& vertexArray,
|
||||
const Array<Face>& faceArray,
|
||||
const Array< Array<int> >& adjacentFaceArray,
|
||||
Array<Vector3>& vertexNormalArray,
|
||||
Array<Vector3>& faceNormalArray);
|
||||
|
||||
/**
|
||||
Vertex normals are weighted by the area of adjacent faces.
|
||||
Nelson Max showed this is superior to uniform weighting for
|
||||
general meshes in jgt.
|
||||
|
||||
@param vertexNormalArray Output. Unit length
|
||||
@param faceNormalArray Output. Degenerate faces produce zero magnitude normals. Unit length
|
||||
@see weld
|
||||
*/
|
||||
static void computeNormals(
|
||||
const Array<Vector3>& vertexGeometry,
|
||||
const Array<Face>& faceArray,
|
||||
const Array<Vertex>& vertexArray,
|
||||
Array<Vector3>& vertexNormalArray,
|
||||
Array<Vector3>& faceNormalArray);
|
||||
|
||||
/** Computes unit length normals in place using the other computeNormals methods.
|
||||
If you already have a face array use another method; it will be faster.
|
||||
@see weld*/
|
||||
static void computeNormals(
|
||||
Geometry& geometry,
|
||||
const Array<int>& indexArray);
|
||||
|
||||
/**
|
||||
Computes face normals only. Significantly faster (especially if
|
||||
normalize is false) than computeNormals.
|
||||
@see weld
|
||||
*/
|
||||
static void computeFaceNormals(
|
||||
const Array<Vector3>& vertexArray,
|
||||
const Array<Face>& faceArray,
|
||||
Array<Vector3>& faceNormals,
|
||||
bool normalize = true);
|
||||
|
||||
/**
|
||||
Classifies each face as a backface or a front face relative
|
||||
to the observer point P (which is at infinity when P.w = 0).
|
||||
A face with normal exactly perpendicular to the observer vector
|
||||
may be classified as either a front or a back face arbitrarily.
|
||||
*/
|
||||
static void identifyBackfaces(
|
||||
const Array<Vector3>& vertexArray,
|
||||
const Array<Face>& faceArray,
|
||||
const Vector4& P,
|
||||
Array<bool>& backface);
|
||||
|
||||
/** A faster version of identifyBackfaces for the case where
|
||||
face normals have already been computed */
|
||||
static void identifyBackfaces(
|
||||
const Array<Vector3>& vertexArray,
|
||||
const Array<Face>& faceArray,
|
||||
const Vector4& P,
|
||||
Array<bool>& backface,
|
||||
const Array<Vector3>& faceNormals);
|
||||
|
||||
/**
|
||||
Welds nearby and colocated elements of the <I>oldVertexArray</I> together so that
|
||||
<I>newVertexArray</I> contains no vertices within <I>radius</I> of one another.
|
||||
Every vertex in newVertexPositions also appears in oldVertexPositions.
|
||||
This is useful for downsampling meshes and welding cracks created by artist errors
|
||||
or numerical imprecision.
|
||||
|
||||
The two integer arrays map indices back and forth between the arrays according to:
|
||||
<PRE>
|
||||
oldVertexArray[toOld[ni]] == newVertexArray[ni]
|
||||
oldVertexArray[oi] == newVertexArray[toNew[ni]]
|
||||
</PRE>
|
||||
|
||||
Note that newVertexPositions is never longer than oldVertexPositions
|
||||
and is shorter when vertices are welded.
|
||||
|
||||
Welding with a large radius will effectively compute a lower level of detail for
|
||||
the mesh.
|
||||
|
||||
The welding method runs in roughly linear time in the length of oldVertexArray--
|
||||
a uniform spatial grid is used to achieve nearly constant time vertex collapses
|
||||
for uniformly distributed vertices.
|
||||
|
||||
It is sometimes desirable to keep the original vertex ordering but
|
||||
identify the unique vertices. The following code computes
|
||||
array canonical s.t. canonical[v] = first occurance of
|
||||
a vertex near oldVertexPositions[v] in oldVertexPositions.
|
||||
|
||||
<PRE>
|
||||
Array<int> canonical(oldVertexPositions.size()), toNew, toOld;
|
||||
computeWeld(oldVertexPositions, Array<Vector3>(), toNew, toOld, radius);
|
||||
for (int v = 0; v < canonical.size(); ++v) {
|
||||
canonical[v] = toOld[toNew[v]];
|
||||
}
|
||||
</PRE>
|
||||
|
||||
See also G3D::MeshAlg::weldAdjacency.
|
||||
|
||||
@cite The method is that described as the 'Grouper' in Baum, Mann, Smith, and Winget,
|
||||
Making Radiosity Usable: Automatic Preprocessing and Meshing Techniques for
|
||||
the Generation of Accurate Radiosity Solutions, Computer Graphics vol 25, no 4, July 1991.
|
||||
|
||||
@deprecated Use weld.
|
||||
*/
|
||||
static void computeWeld(
|
||||
const Array<Vector3>& oldVertexPositions,
|
||||
Array<Vector3>& newVertexPositions,
|
||||
Array<int>& toNew,
|
||||
Array<int>& toOld,
|
||||
double radius = fuzzyEpsilon);
|
||||
|
||||
/**
|
||||
Modifies the face, edge, and vertex arrays in place so that
|
||||
colocated (within radius) vertices are treated as identical.
|
||||
Note that the vertexArray and corresponding geometry will
|
||||
contain elements that are no longer used. In the vertexArray,
|
||||
these elements are initialized to MeshAlg::Vertex() but not
|
||||
removed (because removal would change the indexing).
|
||||
|
||||
This is a good preprocessing step for algorithms that are only
|
||||
concerned with the shape of a mesh (e.g. cartoon rendering, fur, shadows)
|
||||
and not the indexing of the vertices.
|
||||
|
||||
Use this method when you have already computed adjacency information
|
||||
and want to collapse colocated vertices within that data without
|
||||
disturbing the actual mesh vertices or indexing scheme.
|
||||
|
||||
If you have not computed adjacency already, use MeshAlg::computeWeld
|
||||
instead and compute adjacency information after welding.
|
||||
|
||||
@deprecated Use weld.
|
||||
|
||||
@param faceArray Mutated in place. Size is maintained (degenerate
|
||||
faces are <b>not</B> removed).
|
||||
@param edgeArray Mutated in place. May shrink if boundary edges
|
||||
are welded together.
|
||||
@param vertexArray Mutated in place. Size is maintained (duplicate
|
||||
vertices contain no adjacency info).
|
||||
*/
|
||||
static void weldAdjacency(
|
||||
const Array<Vector3>& originalGeometry,
|
||||
Array<Face>& faceArray,
|
||||
Array<Edge>& edgeArray,
|
||||
Array<Vertex>& vertexArray,
|
||||
double radius = fuzzyEpsilon);
|
||||
|
||||
|
||||
/**
|
||||
Counts the number of edges (in an edge array returned from
|
||||
MeshAlg::computeAdjacency) that have only one adjacent face.
|
||||
*/
|
||||
static int countBoundaryEdges(const Array<Edge>& edgeArray);
|
||||
|
||||
|
||||
/**
|
||||
Generates an array of integers from start to start + n - 1 that have run numbers
|
||||
in series then omit the next skip before the next run. Useful for turning
|
||||
a triangle list into an indexed face set.
|
||||
|
||||
Example:
|
||||
<PRE>
|
||||
createIndexArray(10, x);
|
||||
// x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
|
||||
createIndexArray(5, x, 2);
|
||||
// x = [2, 3, 4, 5, 6, 7]
|
||||
|
||||
createIndexArray(6, x, 0, 2, 1);
|
||||
// x = [0, 1, 3, 4, 6, 7]
|
||||
</PRE>
|
||||
*/
|
||||
static void createIndexArray(
|
||||
int n,
|
||||
Array<int>& array,
|
||||
int start = 0,
|
||||
int run = 1,
|
||||
int skip = 0);
|
||||
|
||||
/**
|
||||
Computes a conservative, near-optimal axis aligned bounding box and sphere.
|
||||
|
||||
@cite The bounding sphere uses the method from J. Ritter. An effcient bounding sphere. In Andrew S. Glassner, editor, Graphics Gems. Academic Press, Boston, MA, 1990.
|
||||
|
||||
*/
|
||||
static void computeBounds(const Array<Vector3>& vertex, class AABox& box, class Sphere& sphere);
|
||||
|
||||
/** Computes bounds for a subset of the vertices. It is ok if vertices appear more than once in the index array. */
|
||||
static void computeBounds(const Array<Vector3>& vertex, const Array<int>& index, class AABox& box, class Sphere& sphere);
|
||||
|
||||
/**
|
||||
In debug mode, asserts that the adjacency references between the
|
||||
face, edge, and vertex array are consistent.
|
||||
*/
|
||||
static void debugCheckConsistency(
|
||||
const Array<Face>& faceArray,
|
||||
const Array<Edge>& edgeArray,
|
||||
const Array<Vertex>& vertexArray);
|
||||
|
||||
/**
|
||||
Generates a unit square in the X-Z plane composed of a grid of wCells x hCells
|
||||
squares and then transforms it by xform.
|
||||
|
||||
@param vertex Output vertices
|
||||
@param texCoord Output texture coordinates
|
||||
@param index Output triangle list indices
|
||||
@param textureScale Lower-right texture coordinate
|
||||
@param spaceCentered If true, the coordinates generated are centered at the origin before the transformation.
|
||||
@param twoSided If true, matching top and bottom planes are generated.
|
||||
\param elevation If non-NULL, values from this image are used as elevations. Apply an \a xform to adjust the scale
|
||||
*/
|
||||
static void generateGrid(
|
||||
Array<Vector3>& vertex,
|
||||
Array<Vector2>& texCoord,
|
||||
Array<int>& index,
|
||||
int wCells = 10,
|
||||
int hCells = 10,
|
||||
const Vector2& textureScale = Vector2(1,1),
|
||||
bool spaceCentered = true,
|
||||
bool twoSided = true,
|
||||
const CoordinateFrame& xform = CoordinateFrame(),
|
||||
const Image1::Ref& elevation = NULL);
|
||||
|
||||
/** Converts quadlist (QUADS),
|
||||
triangle fan (TRIANGLE_FAN),
|
||||
tristrip(TRIANGLE_STRIP), and quadstrip (QUAD_STRIP) indices into
|
||||
triangle list (TRIANGLES) indices and appends them to outIndices. */
|
||||
template<class IndexType>
|
||||
static void toIndexedTriList(
|
||||
const Array<IndexType>& inIndices,
|
||||
MeshAlg::Primitive inType,
|
||||
Array<IndexType>& outIndices) {
|
||||
|
||||
debugAssert(
|
||||
inType == PrimitiveType::TRIANGLE_STRIP ||
|
||||
inType == PrimitiveType::TRIANGLE_FAN ||
|
||||
inType == PrimitiveType::QUADS ||
|
||||
inType == PrimitiveType::QUAD_STRIP);
|
||||
|
||||
const int inSize = inIndices.size();
|
||||
|
||||
switch(inType) {
|
||||
case PrimitiveType::TRIANGLE_FAN:
|
||||
{
|
||||
debugAssert(inSize >= 3);
|
||||
|
||||
int N = outIndices.size();
|
||||
outIndices.resize(N + (inSize - 2) * 3);
|
||||
|
||||
for (IndexType i = 1, outIndex = N; i <= (inSize - 2); ++i, outIndex += 3) {
|
||||
outIndices[outIndex] = inIndices[0];
|
||||
outIndices[outIndex + 1] = inIndices[i];
|
||||
outIndices[outIndex + 2] = inIndices[i + 1];
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PrimitiveType::TRIANGLE_STRIP:
|
||||
{
|
||||
debugAssert(inSize >= 3);
|
||||
|
||||
int N = outIndices.size();
|
||||
outIndices.resize(N + (inSize - 2) * 3);
|
||||
|
||||
bool atEven = false;
|
||||
for (IndexType i = 0, outIndex = N; i <= (inSize - 2); ++i, outIndex += 3) {
|
||||
if (atEven) {
|
||||
outIndices[outIndex] = inIndices[i + 1];
|
||||
outIndices[outIndex + 1] = inIndices[i];
|
||||
outIndices[outIndex + 2] = inIndices[i + 2];
|
||||
atEven = false;
|
||||
} else {
|
||||
outIndices[outIndex] = inIndices[i];
|
||||
outIndices[outIndex + 1] = inIndices[i + 1];
|
||||
outIndices[outIndex + 2] = inIndices[i + 2];
|
||||
atEven = true;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PrimitiveType::QUADS:
|
||||
{
|
||||
debugAssert(inIndices.size() >= 4);
|
||||
|
||||
int N = outIndices.size();
|
||||
outIndices.resize(N + (inSize / 4) * 3);
|
||||
|
||||
for (IndexType i = 0, outIndex = N; i <= (inSize - 4); i += 4, outIndex += 6) {
|
||||
outIndices[outIndex] = inIndices[i];
|
||||
outIndices[outIndex + 1] = inIndices[i + 1];
|
||||
outIndices[outIndex + 2] = inIndices[i + 3];
|
||||
outIndices[outIndex + 3] = inIndices[i + 1];
|
||||
outIndices[outIndex + 4] = inIndices[i + 2];
|
||||
outIndices[outIndex + 5] = inIndices[i + 3];
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PrimitiveType::QUAD_STRIP:
|
||||
{
|
||||
debugAssert(inIndices.size() >= 4);
|
||||
|
||||
int N = outIndices.size();
|
||||
outIndices.resize(N + (inSize - 2) * 3);
|
||||
|
||||
for (IndexType i = 0, outIndex = N; i <= (inSize - 2); i += 2, outIndex += 6) {
|
||||
outIndices[outIndex] = inIndices[i];
|
||||
outIndices[outIndex + 1] = inIndices[i + 1];
|
||||
outIndices[outIndex + 2] = inIndices[i + 2];
|
||||
outIndices[outIndex + 3] = inIndices[i + 2];
|
||||
outIndices[outIndex + 4] = inIndices[i + 1];
|
||||
outIndices[outIndex + 5] = inIndices[i + 3];
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
alwaysAssertM(false, "Illegal argument");
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
Helper for computeAdjacency. If a directed edge with index e already
|
||||
exists from i0 to i1 then e is returned. If a directed edge with index e
|
||||
already exists from i1 to i0, ~e is returned (the complement) and
|
||||
edgeArray[e] is set to f. Otherwise, a new edge is created from i0 to i1
|
||||
with first face index f and its index is returned.
|
||||
|
||||
@param vertexArray Vertex positions to use when deciding colocation.
|
||||
|
||||
@param area Area of face f. When multiple edges of the same direction
|
||||
are found between the same vertices (usually because of degenerate edges)
|
||||
the face with larger area is kept in the edge table.
|
||||
*/
|
||||
static int findEdgeIndex(
|
||||
const Array<Vector3>& vertexArray,
|
||||
Array<Edge>& geometricEdgeArray,
|
||||
int i0, int i1, int f, double area);
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
82
dep/include/g3dlite/G3D/MeshBuilder.h
Normal file
82
dep/include/g3dlite/G3D/MeshBuilder.h
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
/**
|
||||
@file MeshBuilder.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2002-02-27
|
||||
@edited 2004-10-04
|
||||
*/
|
||||
#ifndef G3D_MESHBUILDER_H
|
||||
#define G3D_MESHBUILDER_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Array.h"
|
||||
#include "G3D/Vector3.h"
|
||||
#include "G3D/Triangle.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
Allows creation of optimized watertight meshes from unoptimized polygon soups.
|
||||
See also G3D::MeshAlg for algorithms that operate on the output.
|
||||
*/
|
||||
class MeshBuilder {
|
||||
public:
|
||||
|
||||
/**
|
||||
Set setWeldRadius to AUTO_WELD to weld vertices closer than 1/2
|
||||
the smallest edge length in a model.
|
||||
*/
|
||||
enum {AUTO_WELD = -100};
|
||||
|
||||
private:
|
||||
/** Indices of vertices in <B>or near</B> a grid cell. */
|
||||
typedef Array<int> List;
|
||||
|
||||
std::string name;
|
||||
|
||||
/**
|
||||
All of the triangles, as a long triangle list.
|
||||
*/
|
||||
Array<Vector3> triList;
|
||||
|
||||
void centerTriList();
|
||||
void computeBounds(Vector3& min, Vector3& max);
|
||||
|
||||
bool _twoSided;
|
||||
|
||||
/** Collapse radius */
|
||||
double close;
|
||||
|
||||
public:
|
||||
|
||||
inline MeshBuilder(bool twoSided = false) : _twoSided(twoSided), close(AUTO_WELD) {}
|
||||
|
||||
/** Writes the model to the arrays, which can then be used with
|
||||
G3D::IFSModel::save and G3D::MeshAlg */
|
||||
void commit(std::string& name, Array<int>& indexArray, Array<Vector3>& vertexArray);
|
||||
|
||||
/**
|
||||
Adds a new triangle to the model. (Counter clockwise)
|
||||
*/
|
||||
void addTriangle(const Vector3& a, const Vector3& b, const Vector3& c);
|
||||
|
||||
/**
|
||||
Adds two new triangles to the model. (Counter clockwise)
|
||||
*/
|
||||
void addQuad(const Vector3& a, const Vector3& b, const Vector3& c, const Vector3& d);
|
||||
|
||||
void addTriangle(const Triangle& t);
|
||||
|
||||
void setName(const std::string& n);
|
||||
|
||||
/** Vertices within this distance are considered identical.
|
||||
Use AUTO_WELD (the default) to have the distance be a function of the model size.*/
|
||||
void setWeldRadius(double r) {
|
||||
close = r;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
132
dep/include/g3dlite/G3D/NetAddress.h
Normal file
132
dep/include/g3dlite/G3D/NetAddress.h
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
#ifndef G3D_NETADDRESS_H
|
||||
#define G3D_NETADDRESS_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Table.h"
|
||||
|
||||
/** These control the version of Winsock used by G3D.
|
||||
Version 2.0 is standard for G3D 6.09 and later.
|
||||
Version 1.1 is standard for G3D 6.08 and earlier.
|
||||
*/
|
||||
#define G3D_WINSOCK_MAJOR_VERSION 2
|
||||
#define G3D_WINSOCK_MINOR_VERSION 0
|
||||
|
||||
#ifdef G3D_WIN32
|
||||
# if (G3D_WINSOCK_MAJOR_VERSION == 2)
|
||||
# include <winsock2.h>
|
||||
# elif (G3D_WINSOCK_MAJOR_VERSION == 1)
|
||||
# include <winsock.h>
|
||||
# endif
|
||||
#else
|
||||
# include <sys/types.h>
|
||||
# include <sys/socket.h>
|
||||
# include <netinet/in.h>
|
||||
# ifndef SOCKADDR_IN
|
||||
# define SOCKADDR_IN struct sockaddr_in
|
||||
# endif
|
||||
# ifndef SOCKET
|
||||
# define SOCKET int
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include "G3D/g3dmath.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
class NetAddress {
|
||||
private:
|
||||
friend class NetworkDevice;
|
||||
friend class LightweightConduit;
|
||||
friend class ReliableConduit;
|
||||
|
||||
/** Host byte order */
|
||||
void init(uint32 host, uint16 port);
|
||||
void init(const std::string& hostname, uint16 port);
|
||||
NetAddress(const SOCKADDR_IN& a);
|
||||
NetAddress(const struct in_addr& addr, uint16 port = 0);
|
||||
|
||||
SOCKADDR_IN addr;
|
||||
|
||||
public:
|
||||
/**
|
||||
In host byte order
|
||||
*/
|
||||
NetAddress(uint32 host, uint16 port = 0);
|
||||
|
||||
/**
|
||||
@param port Specified in host byte order (i.e., don't worry about endian issues)
|
||||
*/
|
||||
NetAddress(const std::string& hostname, uint16 port);
|
||||
|
||||
/**
|
||||
@param hostnameAndPort in the form "hostname:port" or "ip:port"
|
||||
*/
|
||||
NetAddress(const std::string& hostnameAndPort);
|
||||
|
||||
/**
|
||||
@deprecated Use G3D::NetworkDevice::broadcastAddressArray()
|
||||
|
||||
@brief Creates a UDP broadcast address for use with a
|
||||
G3D::LightweightConduit.
|
||||
|
||||
UDP broadcast allows one machine to send a packet to all machines
|
||||
on the same local network. The IP portion of the address is
|
||||
0xFFFFFFFF, which indicates "broadcast" to the underlying socket
|
||||
API. This feature is not available with the connection-based TCP
|
||||
protocol abstracted by G3D::ReliableConduit; use multisend
|
||||
instead.
|
||||
*/
|
||||
static NetAddress broadcastAddress(uint16 port);
|
||||
|
||||
NetAddress();
|
||||
|
||||
void serialize(class BinaryOutput& b) const;
|
||||
void deserialize(class BinaryInput& b);
|
||||
|
||||
/** @brief Returns true if this is not an illegal address. */
|
||||
bool ok() const;
|
||||
|
||||
/** @brief Returns a value in host format (i.e., don't worry about
|
||||
endian issues) */
|
||||
inline uint32 ip() const {
|
||||
return ntohl(addr.sin_addr.s_addr);
|
||||
//return ntohl(addr.sin_addr.S_un.S_addr);
|
||||
}
|
||||
|
||||
inline uint16 port() const {
|
||||
return ntohs(addr.sin_port);
|
||||
}
|
||||
|
||||
std::string ipString() const;
|
||||
std::string toString() const;
|
||||
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const NetAddress&);
|
||||
|
||||
} // namespace G3D
|
||||
|
||||
template <> struct HashTrait<G3D::NetAddress> {
|
||||
static size_t hashCode(const G3D::NetAddress& key) {
|
||||
return static_cast<size_t>(key.ip() + (static_cast<G3D::uint32>(key.port()) << 16));
|
||||
}
|
||||
};
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
Two addresses may point to the same computer but be != because
|
||||
they have different IP's.
|
||||
*/
|
||||
inline bool operator==(const NetAddress& a, const NetAddress& b) {
|
||||
return (a.ip() == b.ip()) && (a.port() == b.port());
|
||||
}
|
||||
|
||||
|
||||
inline bool operator!=(const NetAddress& a, const NetAddress& b) {
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
} // namespace G3D
|
||||
|
||||
#endif
|
||||
738
dep/include/g3dlite/G3D/NetworkDevice.h
Normal file
738
dep/include/g3dlite/G3D/NetworkDevice.h
Normal file
|
|
@ -0,0 +1,738 @@
|
|||
/**
|
||||
@file NetworkDevice.h
|
||||
|
||||
These classes abstract networking from the socket level to a
|
||||
serialized messaging style that is more appropriate for games. The
|
||||
performance has been tuned for sending many small messages. The
|
||||
message protocol contains a header that prevents them from being used
|
||||
with raw UDP/TCP (e.g. connecting to an HTTP server).
|
||||
|
||||
LightweightConduit and ReliableConduits have different interfaces
|
||||
because they have different semantics. You would never want to
|
||||
interchange them without rewriting the surrounding code.
|
||||
|
||||
NetworkDevice creates conduits because they need access to a global
|
||||
log pointer and because I don't want non-reference counted conduits
|
||||
being created.
|
||||
|
||||
Be careful with threads and reference counting. The reference
|
||||
counters are not threadsafe, and are also not updated correctly if a
|
||||
thread is explicitly killed. Since the conduits will be passed by
|
||||
const XConduitRef& most of the time this doesn't appear as a major
|
||||
problem. With non-blocking conduits, you should need few threads
|
||||
anyway.
|
||||
|
||||
LightweightConduits preceed each message with a 4-byte host order
|
||||
unsigned integer that is the message type. This does not appear in
|
||||
the message serialization/deserialization.
|
||||
|
||||
ReliableConduits preceed each message with two 4-byte host order
|
||||
unsigned integers. The first is the message type and the second
|
||||
indicates the length of the rest of the data. The size does not
|
||||
include the size of the header itself. The minimum message is 9
|
||||
bytes:a 4-byte type, a 4-byte header equal to "1", and one byte of data.
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
@created 2002-11-22
|
||||
@edited 2006-11-25
|
||||
*/
|
||||
|
||||
#ifndef G3D_NETWORKDEVICE_H
|
||||
#define G3D_NETWORKDEVICE_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/NetAddress.h"
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include "G3D/g3dmath.h"
|
||||
|
||||
#include "G3D/ReferenceCount.h"
|
||||
#include "G3D/Array.h"
|
||||
#include "G3D/BinaryOutput.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
class TextOutput;
|
||||
|
||||
class Conduit : public ReferenceCountedObject {
|
||||
protected:
|
||||
friend class NetworkDevice;
|
||||
friend class NetListener;
|
||||
|
||||
uint64 mSent;
|
||||
uint64 mReceived;
|
||||
uint64 bSent;
|
||||
uint64 bReceived;
|
||||
|
||||
SOCKET sock;
|
||||
|
||||
/**
|
||||
Used for serialization. One per socket
|
||||
to make this threadsafe.
|
||||
*/
|
||||
BinaryOutput binaryOutput;
|
||||
|
||||
Conduit();
|
||||
|
||||
public:
|
||||
|
||||
virtual ~Conduit();
|
||||
uint64 bytesSent() const;
|
||||
uint64 messagesSent() const;
|
||||
uint64 bytesReceived() const;
|
||||
uint64 messagesReceived() const;
|
||||
|
||||
/**
|
||||
If true, receive will return true.
|
||||
*/
|
||||
virtual bool messageWaiting();
|
||||
|
||||
/**
|
||||
Returns the type of the waiting message (i.e. the type supplied
|
||||
with send). The return value is zero when there is no message
|
||||
waiting.
|
||||
|
||||
One way to use this is to have a Table mapping message types to
|
||||
pre-allocated subclasses so receiving looks like:
|
||||
|
||||
<PRE>
|
||||
// My base class for messages.
|
||||
class Message {
|
||||
virtual void serialize(BinaryOutput&) const;
|
||||
virtual void deserialize(BinaryInput&);
|
||||
virtual void process() = 0;
|
||||
};
|
||||
|
||||
Message* m = table[conduit->waitingMessageType()];
|
||||
conduit->receive(m);
|
||||
m->process();
|
||||
</PRE>
|
||||
|
||||
Another is to simply switch on the message type:
|
||||
|
||||
<pre>
|
||||
switch (conduit->waitingMessageType()) {
|
||||
case 0:
|
||||
// No message
|
||||
break;
|
||||
|
||||
case ENTITY_SPAWN_MSG:
|
||||
{
|
||||
EntitySpawnMsg m;
|
||||
condiut->receive(m);
|
||||
spawnEntity(m.id, m.position, m.modelID);
|
||||
}
|
||||
break;
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
*/
|
||||
virtual uint32 waitingMessageType() = 0;
|
||||
|
||||
/** Returns true if the connection is ok. */
|
||||
bool ok() const;
|
||||
};
|
||||
|
||||
typedef ReferenceCountedPointer<class ReliableConduit> ReliableConduitRef;
|
||||
|
||||
#ifdef __GNUC__
|
||||
// Workaround for a known bug in gcc 4.x where htonl produces
|
||||
// a spurrious warning.
|
||||
// http://gcc.gnu.org/ml/gcc-bugs/2005-10/msg03270.html
|
||||
uint32 gcchtonl(uint32);
|
||||
#endif
|
||||
|
||||
// Messaging and stream APIs must be supported on a single class because
|
||||
// sometimes an application will switch modes on a single socket. For
|
||||
// example, when transferring 3D level geometry during handshaking with
|
||||
// a game server.
|
||||
/**
|
||||
A conduit that guarantees messages will arrive, intact and in order.
|
||||
Create on the client using NetworkDevice::createReliableConduit and
|
||||
on the server using NetListener::waitForConnection. Set the reference
|
||||
counted pointer to NULL to disconnect.
|
||||
|
||||
To construct a ReliableConduit:
|
||||
<OL>
|
||||
<LI> Create a G3D::NetworkDevice (if you are using G3D::GApp, it creates
|
||||
one for you) on the client and on the server.
|
||||
<LI> On the server, create a G3D::NetListener using
|
||||
G3D::NetworkDevice::createListener
|
||||
<LI> On the server, invoke G3D::NetListener::waitForConnection.
|
||||
<LI> On the client, call G3D::NetworkDevice::createReliableConduit.
|
||||
You will need the server's G3D::NetAddress. Consider using
|
||||
G3D::Discovery::Client to find it via broadcasting.
|
||||
</OL>
|
||||
|
||||
*/
|
||||
class ReliableConduit : public Conduit {
|
||||
private:
|
||||
friend class NetworkDevice;
|
||||
friend class NetListener;
|
||||
|
||||
enum State {RECEIVING, HOLDING, NO_MESSAGE} state;
|
||||
|
||||
NetAddress addr;
|
||||
|
||||
/**
|
||||
Type of the incoming message.
|
||||
*/
|
||||
uint32 messageType;
|
||||
|
||||
/**
|
||||
Total size of the incoming message (read from the header).
|
||||
*/
|
||||
uint32 messageSize;
|
||||
|
||||
/** Shared buffer for receiving messages. */
|
||||
void* receiveBuffer;
|
||||
|
||||
/** Total size of the receiveBuffer. */
|
||||
size_t receiveBufferTotalSize;
|
||||
|
||||
/** Size occupied by the current message... so far. This will be
|
||||
equal to messageSize when the whole message has arrived.
|
||||
*/
|
||||
size_t receiveBufferUsedSize;
|
||||
|
||||
ReliableConduit(const NetAddress& addr);
|
||||
|
||||
ReliableConduit(const SOCKET& sock,
|
||||
const NetAddress& addr);
|
||||
|
||||
template<typename T> static void serializeMessage
|
||||
(uint32 t, const T& m, BinaryOutput& b) {
|
||||
|
||||
b.writeUInt32(t);
|
||||
|
||||
// Reserve space for the 4 byte size header
|
||||
b.writeUInt32(0);
|
||||
|
||||
size_t L = b.length();
|
||||
m.serialize(b);
|
||||
if ((size_t)b.length() == L) {
|
||||
// No data was created by serialization.
|
||||
// We need to send at least one byte because receive assumes that
|
||||
// a zero length message is an error.
|
||||
b.writeUInt8(0xFF);
|
||||
}
|
||||
|
||||
uint32 len = b.size() - 8;
|
||||
|
||||
// We send the length first to tell recv how much data to read.
|
||||
// Here we abuse BinaryOutput a bit and write directly into
|
||||
// its buffer, violating the abstraction.
|
||||
// Note that we write to the second set of 4 bytes, which is
|
||||
// the size field.
|
||||
uint32* lenPtr = ((uint32*)b.getCArray()) + 1;
|
||||
#if defined(__GNUC__)
|
||||
*lenPtr = gcchtonl(len);
|
||||
#else
|
||||
*lenPtr = htonl(len);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void sendBuffer(const BinaryOutput& b);
|
||||
|
||||
/** Accumulates whatever part of the message (not the header) is
|
||||
still waiting on the socket into the receiveBuffer during
|
||||
state = RECEIVING mode. Closes the socket if anything goes
|
||||
wrong. When receiveBufferUsedSize == messageSize, the entire
|
||||
message has arrived. */
|
||||
void receiveIntoBuffer();
|
||||
|
||||
/** Receives the messageType and messageSize from the socket. */
|
||||
void receiveHeader();
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
Client invokes this to connect to a server. The call blocks until the
|
||||
conduit is opened. The conduit will not be ok() if it fails.
|
||||
*/
|
||||
static ReliableConduitRef create(const NetAddress& address);
|
||||
|
||||
/** Closes the socket. */
|
||||
~ReliableConduit();
|
||||
|
||||
|
||||
// The message is actually copied from the socket to an internal buffer during
|
||||
// this call. Receive only deserializes.
|
||||
virtual bool messageWaiting();
|
||||
|
||||
/**
|
||||
Serializes the message and schedules it to be sent as soon as possible,
|
||||
and then returns immediately. The message can be any <B>class</B> with
|
||||
a serialize and deserialize method. On the receiving side,
|
||||
use G3D::ReliableConduit::waitingMessageType() to detect the incoming
|
||||
message and then invoke G3D::ReliableConduit::receive(msg) where msg
|
||||
is of the same class as the message that was sent.
|
||||
|
||||
The actual data sent across the network is preceeded by the
|
||||
message type and the size of the serialized message as a 32-bit
|
||||
integer. The size is sent because TCP is a stream protocol and
|
||||
doesn't have a concept of discrete messages.
|
||||
*/
|
||||
template<typename T> inline void send(uint32 type, const T& message) {
|
||||
binaryOutput.reset();
|
||||
serializeMessage(type, message, binaryOutput);
|
||||
sendBuffer(binaryOutput);
|
||||
}
|
||||
|
||||
/** Sends an empty message with the given type. Useful for sending
|
||||
commands that have no parameters. */
|
||||
void send(uint32 type);
|
||||
|
||||
/** Send the same message to a number of conduits. Useful for sending
|
||||
data from a server to many clients (only serializes once). */
|
||||
template<typename T>
|
||||
inline static void multisend(
|
||||
const Array<ReliableConduitRef>& array,
|
||||
uint32 type,
|
||||
const T& m) {
|
||||
|
||||
if (array.size() > 0) {
|
||||
array[0]->binaryOutput.reset();
|
||||
serializeMessage(type, m, array[0]->binaryOutput);
|
||||
|
||||
for (int i = 0; i < array.size(); ++i) {
|
||||
array[i]->sendBuffer(array[0]->binaryOutput);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual uint32 waitingMessageType();
|
||||
|
||||
/**
|
||||
If a message is waiting, deserializes the waiting message into
|
||||
message and returns true, otherwise returns false. You can
|
||||
determine the type of the message (and therefore, the class
|
||||
of message) using G3D::ReliableConduit::waitingMessageType().
|
||||
*/
|
||||
template<typename T> inline bool receive(T& message) {
|
||||
if (! messageWaiting()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
debugAssert(state == HOLDING);
|
||||
// Deserialize
|
||||
BinaryInput b((uint8*)receiveBuffer, receiveBufferUsedSize, G3D_LITTLE_ENDIAN, BinaryInput::NO_COPY);
|
||||
message.deserialize(b);
|
||||
|
||||
// Don't let anyone read this message again. We leave the buffer
|
||||
// allocated for the next caller, however.
|
||||
receiveBufferUsedSize = 0;
|
||||
state = NO_MESSAGE;
|
||||
messageType = 0;
|
||||
messageSize = 0;
|
||||
|
||||
// Potentially read the next message.
|
||||
messageWaiting();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Removes the current message from the queue. */
|
||||
inline void receive() {
|
||||
if (! messageWaiting()) {
|
||||
return;
|
||||
}
|
||||
receiveBufferUsedSize = 0;
|
||||
state = NO_MESSAGE;
|
||||
messageType = 0;
|
||||
messageSize = 0;
|
||||
|
||||
// Potentially read the next message.
|
||||
messageWaiting();
|
||||
}
|
||||
|
||||
NetAddress address() const;
|
||||
};
|
||||
|
||||
|
||||
typedef ReferenceCountedPointer<class LightweightConduit> LightweightConduitRef;
|
||||
|
||||
/**
|
||||
Provides fast but unreliable transfer of messages. On a LAN,
|
||||
LightweightConduit will probably never drop messages but you
|
||||
<I>might</I> get your messages out of order. On an internet
|
||||
connection it might drop messages altogether. Messages are never
|
||||
corrupted, however. LightweightConduit requires a little less setup
|
||||
and overhead than ReliableConduit. ReliableConduit guarantees
|
||||
message delivery and order but requires a persistent connection.
|
||||
|
||||
To set up a LightweightConduit (assuming you have already made
|
||||
subclasses of G3D::NetMessage based on your application's
|
||||
pcommunication protocol):
|
||||
|
||||
[Server Side]
|
||||
<OL>
|
||||
<LI> Call LightweightConduit::create(port, true, false),
|
||||
where port is the port on which you will receive messages.
|
||||
|
||||
<LI> Poll LightweightConduit::messageWaiting from your main loop. When
|
||||
it is true (or, equivalently, when LightweightConduit::waitingMessageType
|
||||
is non-zero) there is an incoming message.
|
||||
|
||||
<LI> To read the incoming message, call LightweightConduit::receive with
|
||||
the appropriate class type, which mist have a deserialize method.
|
||||
LightweightConduit::waitingMessageType tells you what class is
|
||||
needed (you make up your own message constants for your program; numbers
|
||||
under 1000 are reserved for G3D's internal use).
|
||||
|
||||
<LI> When done, simply set the G3D::LightweightConduitRef to NULL or let
|
||||
it go out of scope and the conduit cleans itself up automatically.
|
||||
</OL>
|
||||
|
||||
[Client Side]
|
||||
<OL>
|
||||
<LI> Call G3D::LightweightConduit::create(). If you will
|
||||
broadcast to all servers on a LAN, set the third optional argument to
|
||||
true (the default is false for no broadcast). You can also set up the
|
||||
receive port as if it was a server to send and receive from a single
|
||||
LightweightConduit.
|
||||
|
||||
<LI> To send, call G3D::LightweightConduit::send with the target address
|
||||
and a pointer to an instance of the message you want to send.
|
||||
|
||||
<LI> When done, simply set the G3D::LightweightConduitRef to NULL or let
|
||||
it go out of scope and the conduit cleans itself up automatically.
|
||||
|
||||
</OL>
|
||||
*/
|
||||
class LightweightConduit : public Conduit {
|
||||
private:
|
||||
friend class NetworkDevice;
|
||||
|
||||
/**
|
||||
True when waitingForMessageType has read the message
|
||||
from the network into messageType/messageStream.
|
||||
*/
|
||||
bool alreadyReadMessage;
|
||||
|
||||
/**
|
||||
Origin of the received message.
|
||||
*/
|
||||
NetAddress messageSender;
|
||||
|
||||
/**
|
||||
The type of the last message received.
|
||||
*/
|
||||
uint32 messageType;
|
||||
|
||||
/**
|
||||
The message received (the type has already been read off).
|
||||
*/
|
||||
Array<uint8> messageBuffer;
|
||||
|
||||
LightweightConduit(uint16 receivePort, bool enableReceive, bool enableBroadcast);
|
||||
|
||||
void sendBuffer(const NetAddress& a, BinaryOutput& b);
|
||||
|
||||
/** Maximum transmission unit (packet size in bytes) for this socket.
|
||||
May vary between sockets. */
|
||||
int MTU;
|
||||
|
||||
|
||||
template<typename T>
|
||||
void serializeMessage(
|
||||
uint32 type,
|
||||
const T& m,
|
||||
BinaryOutput& b) const {
|
||||
|
||||
debugAssert(type != 0);
|
||||
b.writeUInt32(type);
|
||||
m.serialize(b);
|
||||
b.writeUInt32(1);
|
||||
|
||||
debugAssertM(b.size() < MTU,
|
||||
format("This LightweightConduit is limited to messages of "
|
||||
"%d bytes (Ethernet hardware limit; this is the "
|
||||
"'UDP MTU')", maxMessageSize()));
|
||||
|
||||
if (b.size() >= MTU) {
|
||||
throw LightweightConduit::PacketSizeException(
|
||||
format("This LightweightConduit is limited to messages of "
|
||||
"%d bytes (Ethernet hardware limit; this is the "
|
||||
"'UDP MTU')", maxMessageSize()),
|
||||
b.size() - 4, // Don't count the type header
|
||||
maxMessageSize());
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
static LightweightConduitRef create(uint16 receivePort, bool enableReceive, bool enableBroadcast);
|
||||
|
||||
class PacketSizeException {
|
||||
public:
|
||||
std::string message;
|
||||
int serializedPacketSize;
|
||||
int maxMessageSize;
|
||||
|
||||
inline PacketSizeException(const std::string& m, int s, int b) :
|
||||
message(m),
|
||||
serializedPacketSize(s),
|
||||
maxMessageSize(b) {}
|
||||
};
|
||||
|
||||
/** Closes the socket. */
|
||||
~LightweightConduit();
|
||||
|
||||
/** The maximum length of a message that can be sent
|
||||
(G3D places a small header at the front of each UDP packet;
|
||||
this is already taken into account by the value returned).
|
||||
*/
|
||||
inline int maxMessageSize() const {
|
||||
return MTU - 4;
|
||||
}
|
||||
|
||||
|
||||
template<typename T> inline void send(const NetAddress& a, uint32 type, const T& msg) {
|
||||
binaryOutput.reset();
|
||||
serializeMessage(type, msg, binaryOutput);
|
||||
sendBuffer(a, binaryOutput);
|
||||
}
|
||||
|
||||
/** Send the same message to multiple addresses (only serializes once).
|
||||
Useful when server needs to send to a known list of addresses
|
||||
(unlike direct UDP broadcast to all addresses on the subnet) */
|
||||
template<typename T> inline void send(const Array<NetAddress>& a, uint32 type, const T& m) {
|
||||
binaryOutput.reset();
|
||||
serializeMessage(type, m, binaryOutput);
|
||||
|
||||
for (int i = 0; i < a.size(); ++i) {
|
||||
sendBuffer(a[i], binaryOutput);
|
||||
}
|
||||
}
|
||||
|
||||
bool receive(NetAddress& sender);
|
||||
|
||||
template<typename T> inline bool receive(NetAddress& sender, T& message) {
|
||||
bool r = receive(sender);
|
||||
if (r) {
|
||||
BinaryInput b((messageBuffer.getCArray() + 4),
|
||||
messageBuffer.size() - 4,
|
||||
G3D_LITTLE_ENDIAN, BinaryInput::NO_COPY);
|
||||
message.deserialize(b);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
inline bool receive() {
|
||||
static NetAddress ignore;
|
||||
return receive(ignore);
|
||||
}
|
||||
|
||||
virtual uint32 waitingMessageType();
|
||||
|
||||
|
||||
virtual bool messageWaiting();
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef ReferenceCountedPointer<class NetListener> NetListenerRef;
|
||||
|
||||
/**
|
||||
Runs on the server listening for clients trying to make reliable connections.
|
||||
*/
|
||||
class NetListener : public ReferenceCountedObject {
|
||||
private:
|
||||
|
||||
friend class NetworkDevice;
|
||||
|
||||
SOCKET sock;
|
||||
|
||||
/** Port is in host byte order. */
|
||||
NetListener(uint16 port);
|
||||
|
||||
public:
|
||||
|
||||
static NetListenerRef create(const uint16 port);
|
||||
|
||||
~NetListener();
|
||||
|
||||
/** Block until a connection is received. Returns NULL if
|
||||
something went wrong. */
|
||||
ReliableConduitRef waitForConnection();
|
||||
|
||||
/** True if a client is waiting (i.e. waitForConnection will
|
||||
return immediately). */
|
||||
bool clientWaiting() const;
|
||||
|
||||
bool ok() const;
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
@brief Abstraction of network (socket) functionality.
|
||||
|
||||
An abstraction over sockets that provides a message-based network
|
||||
infrastructure optimized for sending many small (~500 bytes) messages.
|
||||
All functions always return immediately.
|
||||
|
||||
Create only one NetworkDevice per process (a WinSock restriction).
|
||||
|
||||
NetworkDevice is technically not thread safe. However, as long as
|
||||
you use different conduits on different threads (or lock conduits
|
||||
before sending), you will encounter no problems sharing the single
|
||||
NetworkDevice across multiple threads. That is, do not invoke the same
|
||||
Conduit's send or receive method on two threads at once.
|
||||
|
||||
This assumes that the underlying WinSock/BSD sockets implementation
|
||||
is thread safe. That is not guaranteed, but in practice seems
|
||||
to always be true (see
|
||||
http://tangentsoft.net/wskfaq/intermediate.html#threadsafety)
|
||||
|
||||
<hr>
|
||||
|
||||
IP networks use "network byte order" (big-endian) for
|
||||
communicating integers. "Host byte order" is the endian-ness of
|
||||
the local machine (typically little-endian; see
|
||||
System::endian). The C functions htonl() and ntohl() convert 32-bit
|
||||
values between these formats. G3D only ever exposes host byte order,
|
||||
so programmers rarely need to be aware of the distinction.
|
||||
|
||||
*/
|
||||
class NetworkDevice {
|
||||
public:
|
||||
|
||||
/** @brief Description of an ethernet or wireless ethernet adapter.*/
|
||||
class EthernetAdapter {
|
||||
public:
|
||||
/** Reverse-DNS of the ip address.*/
|
||||
std::string hostname;
|
||||
|
||||
/** Name of the adapter */
|
||||
std::string name;
|
||||
|
||||
/** IP address in host byte order.*/
|
||||
uint32 ip;
|
||||
|
||||
/** Subnet mask in host byte order.*/
|
||||
uint32 subnet;
|
||||
|
||||
/** UDP broadcast address in host byte order.*/
|
||||
uint32 broadcast;
|
||||
|
||||
/** MAC (hardware) address, if known */
|
||||
uint8 mac[6];
|
||||
|
||||
EthernetAdapter();
|
||||
|
||||
/** Produces a text description of this adapter */
|
||||
void describe(TextOutput& t) const;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
friend class Conduit;
|
||||
friend class LightweightConduit;
|
||||
friend class ReliableConduit;
|
||||
friend class NetListener;
|
||||
|
||||
bool initialized;
|
||||
|
||||
Array<EthernetAdapter> m_adapterArray;
|
||||
|
||||
/** Broadcast addresses available on this machine,
|
||||
extracted from m_adapterArray.*/
|
||||
Array<uint32> m_broadcastAddresses;
|
||||
|
||||
/** Utility method. */
|
||||
void closesocket(SOCKET& sock) const;
|
||||
|
||||
/** Utility method. Returns true on success.*/
|
||||
bool bind(SOCKET sock, const NetAddress& addr) const;
|
||||
|
||||
/** The global instance */
|
||||
static NetworkDevice* s_instance;
|
||||
|
||||
NetworkDevice();
|
||||
|
||||
bool init();
|
||||
|
||||
void _cleanup();
|
||||
|
||||
/** Called from init to update m_adapterArray and
|
||||
m_broadcastAddresses. */
|
||||
void addAdapter(const EthernetAdapter& a);
|
||||
|
||||
public:
|
||||
|
||||
/** Prints an IP address to a string.
|
||||
@param ip In host byte order.*/
|
||||
static std::string formatIP(uint32 ip);
|
||||
|
||||
/** Prints a MAC address to a string. */
|
||||
static std::string formatMAC(const uint8 mac[6]);
|
||||
|
||||
~NetworkDevice();
|
||||
|
||||
/** Returns the available ethernet adapters for the current
|
||||
machine that are online. Does not include the loopback adapter
|
||||
for localhost.*/
|
||||
inline const Array<EthernetAdapter>& adapterArray() const {
|
||||
return m_adapterArray;
|
||||
}
|
||||
|
||||
/** Returns the (unique) IP addresses for UDP broadcasting
|
||||
extracted from adapterArray(). All are in host byte order. */
|
||||
inline const Array<uint32>& broadcastAddressArray() const {
|
||||
return m_broadcastAddresses;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns NULL if there was a problem initializing the network.
|
||||
*/
|
||||
static NetworkDevice* instance();
|
||||
|
||||
/**
|
||||
Shuts down the network device (destroying the global instance).
|
||||
*/
|
||||
static void cleanup();
|
||||
|
||||
/**
|
||||
Prints a human-readable description of this machine
|
||||
to the text output stream.
|
||||
*/
|
||||
void describeSystem(
|
||||
TextOutput& t);
|
||||
|
||||
void describeSystem(
|
||||
std::string& s);
|
||||
|
||||
/** Returns the name (or one of the names) of this computer */
|
||||
std::string localHostName() const;
|
||||
|
||||
/** There is often more than one address for the local host. This
|
||||
returns all of them.
|
||||
@deprecated Use adapterArray()
|
||||
*/
|
||||
void localHostAddresses(Array<NetAddress>& array) const;
|
||||
};
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
inline uint32 gcchtonl(uint32 x) {
|
||||
// This pragma fools gcc into surpressing all error messages,
|
||||
// including the bogus one that it creates for htonl
|
||||
# pragma GCC system_header
|
||||
return htonl(x);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // G3D namespace
|
||||
|
||||
#ifndef _WIN32
|
||||
#undef SOCKADDR_IN
|
||||
#undef SOCKET
|
||||
#endif
|
||||
|
||||
#endif
|
||||
59
dep/include/g3dlite/G3D/ParseError.h
Normal file
59
dep/include/g3dlite/G3D/ParseError.h
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
/**
|
||||
@file ParseError.h
|
||||
|
||||
@maintainer Morgan McGuire
|
||||
|
||||
@created 2009-11-15
|
||||
@edited 2009-11-15
|
||||
|
||||
Copyright 2000-2009, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
#ifndef G3D_ParseError_h
|
||||
#define G3D_ParseError_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include <string>
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/** Thrown by TextInput, Any, and other parsers on unexpected input. */
|
||||
class ParseError {
|
||||
public:
|
||||
enum {UNKNOWN = -1};
|
||||
|
||||
/** Empty means unknown */
|
||||
std::string filename;
|
||||
|
||||
/** For a binary file, the location of the parse error. -1 if unknown.*/
|
||||
int64 byte;
|
||||
|
||||
/** For a text file, the line number is the line number of start of token which caused the exception. 1 is
|
||||
the first line of the file. -1 means unknown. Note that you can use
|
||||
TextInput::Settings::startingLineNumberOffset to shift the effective line
|
||||
number that is reported by that class.
|
||||
*/
|
||||
int line;
|
||||
|
||||
/** Character number (in the line) of the start of the token which caused the
|
||||
exception. 1 is the character in the line. May be -1 if unknown.
|
||||
*/
|
||||
int character;
|
||||
|
||||
std::string message;
|
||||
|
||||
ParseError() : byte(UNKNOWN), line(UNKNOWN), character(UNKNOWN) {}
|
||||
|
||||
virtual ~ParseError() {}
|
||||
|
||||
ParseError(const std::string& f, int l, int c, const std::string& m) :
|
||||
filename (f), byte(UNKNOWN), line(l), character(c), message(m) {}
|
||||
|
||||
ParseError(const std::string& f, int64 b, const std::string& m) :
|
||||
filename (f), byte(b), line(UNKNOWN), character(UNKNOWN), message(m) {}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
74
dep/include/g3dlite/G3D/PhysicsFrame.h
Normal file
74
dep/include/g3dlite/G3D/PhysicsFrame.h
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
/**
|
||||
@file PhysicsFrame.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2002-07-08
|
||||
@edited 2006-01-10
|
||||
*/
|
||||
|
||||
#ifndef G3D_PHYSICSFRAME_H
|
||||
#define G3D_PHYSICSFRAME_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Vector3.h"
|
||||
#include "G3D/Matrix3.h"
|
||||
#include "G3D/Quat.h"
|
||||
#include "G3D/CoordinateFrame.h"
|
||||
#include <math.h>
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
An RT transformation using a quaternion; suitable for
|
||||
physics integration.
|
||||
|
||||
This interface is in "Beta" and will change in the next release.
|
||||
*/
|
||||
class PhysicsFrame {
|
||||
public:
|
||||
|
||||
Quat rotation;
|
||||
|
||||
/**
|
||||
Takes object space points to world space.
|
||||
*/
|
||||
Vector3 translation;
|
||||
|
||||
/**
|
||||
Initializes to the identity frame.
|
||||
*/
|
||||
PhysicsFrame();
|
||||
|
||||
/**
|
||||
Purely translational force
|
||||
*/
|
||||
PhysicsFrame(const Vector3& translation) : translation(translation) {}
|
||||
|
||||
PhysicsFrame(const CoordinateFrame& coordinateFrame);
|
||||
|
||||
/** Compose: create the transformation that is <I>other</I> followed by <I>this</I>.*/
|
||||
PhysicsFrame operator*(const PhysicsFrame& other) const;
|
||||
|
||||
virtual ~PhysicsFrame() {}
|
||||
|
||||
CoordinateFrame toCoordinateFrame() const;
|
||||
|
||||
/**
|
||||
Linear interpolation (spherical linear for the rotations).
|
||||
*/
|
||||
PhysicsFrame lerp(
|
||||
const PhysicsFrame& other,
|
||||
float alpha) const;
|
||||
|
||||
void deserialize(class BinaryInput& b);
|
||||
|
||||
void serialize(class BinaryOutput& b) const;
|
||||
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
Plane class
|
||||
|
||||
@maintainer Morgan McGuire, matrix@graphics3d.com
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2001-06-02
|
||||
@edited 2004-07-18
|
||||
|
|
@ -15,6 +15,7 @@
|
|||
#include "G3D/platform.h"
|
||||
#include "G3D/Vector3.h"
|
||||
#include "G3D/Vector4.h"
|
||||
#include "G3D/debugAssert.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
|
|
@ -65,6 +66,10 @@ public:
|
|||
|
||||
static Plane fromEquation(float a, float b, float c, float d);
|
||||
|
||||
Plane(class BinaryInput& b);
|
||||
void serialize(class BinaryOutput& b) const;
|
||||
void deserialize(class BinaryInput& b);
|
||||
|
||||
virtual ~Plane() {}
|
||||
|
||||
/**
|
||||
|
|
|
|||
917
dep/include/g3dlite/G3D/PointHashGrid.h
Normal file
917
dep/include/g3dlite/G3D/PointHashGrid.h
Normal file
|
|
@ -0,0 +1,917 @@
|
|||
/**
|
||||
@file PointHashGrid.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
@created 2008-07-01
|
||||
@edited 2009-05-28
|
||||
|
||||
Copyright 2000-2009, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
#ifndef G3D_PointHashGrid_h
|
||||
#define G3D_PointHashGrid_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/EqualsTrait.h"
|
||||
#include "G3D/HashTrait.h"
|
||||
#include "G3D/Vector3.h"
|
||||
#include "G3D/Vector3int32.h"
|
||||
#include "G3D/Array.h"
|
||||
#include "G3D/Table.h"
|
||||
#include "G3D/AABox.h"
|
||||
#include "G3D/Sphere.h"
|
||||
#include "G3D/SmallArray.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
Storage of data in a sparse 3D grid of point-based data. The
|
||||
space cost for <I>n</I> elements is O(<I>n</I>). For data with
|
||||
approximately uniform density (with respect to the radius hint),
|
||||
the time cost of searching for neighbors is O(1).
|
||||
|
||||
<i>Value</i> must be supported by a G3D::PositionTrait,
|
||||
G3D::EqualsTrait, and G3D::HashFunc. overrides are provided for
|
||||
common G3D classes like G3D::Vector3.
|
||||
*/
|
||||
template<class Value,
|
||||
class PosFunc = PositionTrait<Value>,
|
||||
class EqualsFunc = EqualsTrait<Value>,
|
||||
class HashFunc = HashTrait<Vector3int32> >
|
||||
class PointHashGrid {
|
||||
private:
|
||||
|
||||
#define ThisType PointHashGrid<Value, PosFunc, EqualsFunc, HashFunc>
|
||||
|
||||
/** A value annotated with precomputed position and hash code.*/
|
||||
class Entry {
|
||||
public:
|
||||
Vector3 position;
|
||||
Value value;
|
||||
};
|
||||
|
||||
/** One cell of the grid. */
|
||||
typedef Array<Entry> Cell;
|
||||
typedef Table<Vector3int32, Cell, HashFunc> CellTable;
|
||||
|
||||
/** The cube of +/-1 along each dimension. Initialized by initOffsetArray.*/
|
||||
Vector3int32 m_offsetArray[3*3*3];
|
||||
|
||||
/** Incremented every time the data structure is mutated.
|
||||
Used by the iterators to determine if the data structure
|
||||
has changed since iteration began. */
|
||||
int m_epoch;
|
||||
|
||||
/** Extent of a cell along one dimension. */
|
||||
float m_cellWidth;
|
||||
|
||||
/** 1.0 / cell width */
|
||||
float m_invCellWidth;
|
||||
|
||||
/** Conservative bounds; the actual data may be smaller. */
|
||||
AABox m_bounds;
|
||||
|
||||
/** Number of elements. */
|
||||
int m_size;
|
||||
|
||||
/** Non-empty cells indexed by grid position. Actual 3D position is
|
||||
<code>position * m_cellWidth</code>*/
|
||||
CellTable m_data;
|
||||
|
||||
MemoryManager::Ref m_memoryManager;
|
||||
|
||||
/** Intentionally unimplemented: prevent copy construction. */
|
||||
PointHashGrid(const ThisType&);
|
||||
|
||||
|
||||
/** Intentionally unimplemented: prevent assignment. */
|
||||
PointHashGrid& operator=(const ThisType&);
|
||||
|
||||
|
||||
/** Locate the cell and index within that cell containing v. Called by
|
||||
remove() and contains(). */
|
||||
bool find(const Value& v,
|
||||
Vector3int32& foundCellCoord,
|
||||
Cell*& foundCell,
|
||||
int& index) {
|
||||
|
||||
Vector3 pos;
|
||||
PosFunc::getPosition(v, pos);
|
||||
|
||||
Vector3int32 cellCoord;
|
||||
getCellCoord(pos, cellCoord);
|
||||
for (int i = 0; i < 27; ++i) {
|
||||
Vector3int32 c = cellCoord + m_offsetArray[i];
|
||||
Cell* cell = m_data.getPointer(c);
|
||||
if (cell != NULL) {
|
||||
// The cell exists
|
||||
for (int j = 0; j < cell->size(); ++j) {
|
||||
if (EqualsFunc::equals((*cell)[j].value, v)) {
|
||||
foundCell = cell;
|
||||
index = j;
|
||||
foundCellCoord = c;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Not found
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Given a real-space position, returns the cell coord
|
||||
containing it.*/
|
||||
inline void getCellCoord(const Vector3& pos, Vector3int32& cellCoord) const {
|
||||
for (int a = 0; a < 3; ++a) {
|
||||
cellCoord[a] = iFloor(pos[a] * m_invCellWidth);
|
||||
}
|
||||
}
|
||||
|
||||
/** Initializes m_offsetArray. */
|
||||
void initOffsetArray() {
|
||||
int i = 0;
|
||||
Vector3int32 d;
|
||||
for (d.x = -1; d.x <= +1; ++d.x) {
|
||||
for (d.y = -1; d.y <= +1; ++d.y) {
|
||||
for (d.z = -1; d.z <= +1; ++d.z) {
|
||||
m_offsetArray[i] = d;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Put (0, 0, 0) first, so that contains() is most likely to find
|
||||
// the value quickly.
|
||||
i = (1 * 3 + 1) * 3 + 1;
|
||||
debugAssert(m_offsetArray[i] == Vector3int32(0,0,0));
|
||||
Vector3int32 temp = m_offsetArray[0];
|
||||
m_offsetArray[0] = m_offsetArray[i];
|
||||
m_offsetArray[i] = temp;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
@param radiusHint the radius that will typically be used with
|
||||
beginSphereIntersection and beginBoxIntersection. If two <i>Value</i>s are equal,
|
||||
their positions must be within this radius as well.
|
||||
*/
|
||||
PointHashGrid(float radiusHint, const MemoryManager::Ref& m = MemoryManager::create()) : m_size(0), m_memoryManager(m) {
|
||||
initOffsetArray();
|
||||
m_data.clearAndSetMemoryManager(m_memoryManager);
|
||||
|
||||
debugAssertM(radiusHint > 0, "Cell radius must be positive");
|
||||
m_cellWidth = radiusHint;
|
||||
m_invCellWidth = 1.0f / m_cellWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
If radiusHint is negative, it is automatically chosen to put
|
||||
about 5 values in each grid cell (which means about 27 * 5
|
||||
values for each beginIntersection call).
|
||||
*/
|
||||
PointHashGrid(const Array<Value>& init, float radiusHint = -1.0f, const MemoryManager::Ref& m = MemoryManager::create()) : m_size(0), m_memoryManager(m) {
|
||||
initOffsetArray();
|
||||
m_data.clearAndSetMemoryManager(m_memoryManager);
|
||||
|
||||
Vector3 lo(Vector3::inf());
|
||||
Vector3 hi(-lo);
|
||||
|
||||
// Compute bounds
|
||||
Array<Entry> entry(init.size());
|
||||
for (int i = 0; i < entry.size(); ++i) {
|
||||
const Value& value = init[i];
|
||||
Vector3 pos = m_posFunc(value);
|
||||
|
||||
entry[i].value = value;
|
||||
entry[i].hashCode = m_hashFunc(value);
|
||||
entry[i].position = pos;
|
||||
|
||||
lo = lo.min(pos);
|
||||
hi = hi.max(pos);
|
||||
}
|
||||
|
||||
m_bounds = AABox(lo, hi);
|
||||
|
||||
if (radiusHint <= 0) {
|
||||
// Compute a good cell width based on the bounds.
|
||||
//
|
||||
// N numPerCell
|
||||
// ----- = ---------
|
||||
// volume r^3
|
||||
|
||||
float numPerCell = 5;
|
||||
radiusHint =
|
||||
(float)pow(numPerCell * m_bounds.volume() / init.size(), 1.0 / 3.0);
|
||||
|
||||
if (radiusHint == 0) {
|
||||
// Volume must have been zero because all points were colocated.
|
||||
radiusHint = 0.1f;
|
||||
}
|
||||
}
|
||||
|
||||
insert(init);
|
||||
}
|
||||
|
||||
/** Returns the number of elements. */
|
||||
inline int size() const {
|
||||
return m_size;
|
||||
}
|
||||
|
||||
/** Returns a conservative bounding box around the contents. This is
|
||||
conservative because it is not updated when elements are removed. */
|
||||
const AABox& conservativeBoxBounds() const {
|
||||
return m_bounds;
|
||||
}
|
||||
|
||||
/** Insert @a v at position @a p given by <code>getPosition(v, p)</code>.
|
||||
Multiple elements that are equal may be inserted; all copies will be
|
||||
in the data structure. */
|
||||
void insert(const Value& v) {
|
||||
Vector3 pos;
|
||||
PosFunc::getPosition(v, pos);
|
||||
Vector3int32 cellCoord;
|
||||
getCellCoord(pos, cellCoord);
|
||||
|
||||
// See if the cell already exists
|
||||
Cell& cell = m_data.getCreate(cellCoord);
|
||||
|
||||
if (cell.size() == 0) {
|
||||
// Use the same memory manager as for the whole class
|
||||
cell.clearAndSetMemoryManager(m_memoryManager);
|
||||
}
|
||||
|
||||
Entry& entry = cell.next();
|
||||
entry.value = v;
|
||||
entry.position = pos;
|
||||
|
||||
// Update the bounds
|
||||
if (size() == 0) {
|
||||
m_bounds = AABox(pos);
|
||||
} else {
|
||||
m_bounds.merge(pos);
|
||||
}
|
||||
|
||||
++m_size;
|
||||
++m_epoch;
|
||||
}
|
||||
|
||||
|
||||
/** Inserts all elements of the array. */
|
||||
void insert(const Array<Value>& v) {
|
||||
for (int i = 0; i < v.size(); ++i) {
|
||||
insert(v[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** If there are multiple copies of an element, you must
|
||||
delete them multiple times.
|
||||
|
||||
@param shrinkIfNecessary If <b>true</b>, deallocate underlying data
|
||||
structures as they are emptied. False increases performace at
|
||||
the cost of memory overhead for dynamic structures.
|
||||
|
||||
@return true if the element was found.
|
||||
*/
|
||||
bool remove(const Value& v, bool shrinkIfNecessary = true) {
|
||||
Cell* cell = NULL;
|
||||
int index = 0;
|
||||
Vector3int32 cellCoord;
|
||||
|
||||
if (find(v, cellCoord, cell, index)) {
|
||||
cell->fastRemove(index, shrinkIfNecessary);
|
||||
--m_size;
|
||||
++m_epoch;
|
||||
|
||||
if ((cell->size() == 0) && shrinkIfNecessary) {
|
||||
// Remove the cell itself
|
||||
|
||||
// Drop our pointer, which is about to dangle
|
||||
cell = NULL;
|
||||
bool success = m_data.remove(cellCoord);
|
||||
debugAssertM(success, "Data structure corrupt: "
|
||||
"tried to remove a cell that doesn't exist.");
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/** Removes all elements of @v. */
|
||||
void remove(const Array<Value>& v, bool shrink = true) {
|
||||
for (int i = 0; i < v.size(); ++i) {
|
||||
remove(v[i], shrink);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class Iterator {
|
||||
private:
|
||||
friend class ThisType;
|
||||
|
||||
bool m_isEnd;
|
||||
|
||||
const ThisType* m_grid;
|
||||
|
||||
typename CellTable::Iterator m_tableIterator;
|
||||
|
||||
/** Index within m_tableIterator->value of the current value. */
|
||||
int m_arrayIndex;
|
||||
|
||||
const int m_epoch;
|
||||
|
||||
/** End iterator. Note that the m_tableIterator is initialized to the end iterator
|
||||
of a temporary value! This is ok because we'll never look at the value of the
|
||||
m_tableIterator, since we're initializing the "end" Iterator.*/
|
||||
Iterator() : m_isEnd(true), m_grid(NULL), m_tableIterator(CellTable().end()),
|
||||
m_arrayIndex(0), m_epoch(0) {}
|
||||
|
||||
Iterator(const ThisType* grid) :
|
||||
m_isEnd(false),
|
||||
m_grid(grid),
|
||||
m_tableIterator( grid->m_data.begin() ),
|
||||
m_arrayIndex(0),
|
||||
m_epoch(grid->m_epoch) { }
|
||||
|
||||
private:
|
||||
|
||||
const Value& value() const {
|
||||
debugAssert(! m_isEnd);
|
||||
debugAssertM(m_tableIterator->value.size() > m_arrayIndex,
|
||||
"No more elements");
|
||||
return m_tableIterator->value[m_arrayIndex].value;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
inline bool operator!=(const Iterator& other) const {
|
||||
if (other.m_isEnd && m_isEnd) {
|
||||
return false;
|
||||
} else {
|
||||
return (m_isEnd != other.m_isEnd) ||
|
||||
(m_tableIterator != other.m_tableIterator) ||
|
||||
(m_arrayIndex != other.m_arrayIndex);
|
||||
}
|
||||
}
|
||||
|
||||
bool operator==(const Iterator& other) const {
|
||||
return !(*this != other);
|
||||
}
|
||||
|
||||
/** Preincrement */
|
||||
Iterator& operator++() {
|
||||
debugAssert(! m_isEnd);
|
||||
debugAssertM(m_epoch == m_grid->m_epoch,
|
||||
"It is illegal to mutate the HashGrid "
|
||||
"while iterating through it.");
|
||||
|
||||
++m_arrayIndex;
|
||||
|
||||
if (m_arrayIndex >= m_tableIterator->value.size()) {
|
||||
// Move on to the next cell
|
||||
++m_tableIterator;
|
||||
m_arrayIndex = 0;
|
||||
|
||||
// Check to see if we're at the end
|
||||
m_isEnd = (m_tableIterator == m_grid->m_data.end());
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Post increment (slower) */
|
||||
Iterator operator++(int) {
|
||||
debugAssert(! m_isEnd);
|
||||
Iterator old = *this;
|
||||
++(*this);
|
||||
return old;
|
||||
}
|
||||
|
||||
const Value& operator*() const { return value(); }
|
||||
const Value* operator->() const { return &value(); }
|
||||
operator Value*() const { return &value(); }
|
||||
}; // Iterator
|
||||
|
||||
|
||||
/** Iterate through all members. It is an error to mutate the HashGrid
|
||||
while iterating through it. Each member can be accessed by "dereferencing"
|
||||
the iterator:
|
||||
|
||||
<pre>
|
||||
for (Grid::Iterator i = grid.begin(); i != grid.end(), ++i) {
|
||||
const Value& = *i;
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
*/
|
||||
Iterator begin() const {
|
||||
return Iterator(this);
|
||||
}
|
||||
|
||||
const Iterator& end() const {
|
||||
static const Iterator it;
|
||||
return it;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Forward declaration required by older gcc versions for friend declaration in BoxIterator
|
||||
class SphereIterator;
|
||||
class BoxIterator {
|
||||
private:
|
||||
friend class ThisType;
|
||||
friend class SphereIterator;
|
||||
|
||||
bool m_isEnd;
|
||||
|
||||
const ThisType* m_grid;
|
||||
|
||||
/** Lower bound on the boxes covered, inclusive. */
|
||||
Vector3int32 m_lo;
|
||||
|
||||
/** Upper bound on the boxes covered, inclusive.*/
|
||||
Vector3int32 m_hi;
|
||||
|
||||
/** If true, test values against m_box before returning them.*/
|
||||
bool m_exact;
|
||||
|
||||
/** The underlying box in 3D space */
|
||||
AABox m_box;
|
||||
|
||||
/** The iterator winds through the 3D grid between m_lo and (m_lo + m_extent) in
|
||||
Z,Y,X-major order. This is the index keeping track of how
|
||||
far it has come */
|
||||
Vector3int32 m_current;
|
||||
|
||||
/** The current cell. */
|
||||
Cell* m_cell;
|
||||
|
||||
/** Index within m_cell of the current value */
|
||||
int m_arrayIndex;
|
||||
|
||||
const int m_epoch;
|
||||
|
||||
|
||||
/** Called from advance() */
|
||||
void advanceCell() {
|
||||
do {
|
||||
++m_current.x;
|
||||
if (m_current.x > m_hi.x) {
|
||||
m_current.x = m_lo.x;
|
||||
++m_current.y;
|
||||
if (m_current.y > m_hi.y) {
|
||||
m_current.y = m_lo.y;
|
||||
++m_current.z;
|
||||
if (m_current.z > m_hi.z) {
|
||||
m_isEnd = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pick up the new cell
|
||||
m_cell = m_grid->m_data.getPointer(m_current);
|
||||
// Keep advancing if the cell does not exist
|
||||
} while ((m_cell == NULL) || (m_cell->size() == 0));
|
||||
}
|
||||
|
||||
/** Advance to the next value */
|
||||
void advance() {
|
||||
debugAssert(! m_isEnd);
|
||||
|
||||
do {
|
||||
++m_arrayIndex;
|
||||
bool inConstructor = (m_cell == NULL);
|
||||
if (inConstructor || m_arrayIndex >= m_cell->size()) {
|
||||
advanceCell();
|
||||
m_arrayIndex = 0;
|
||||
|
||||
if (m_isEnd) {
|
||||
// Ran out of values
|
||||
return;
|
||||
}
|
||||
debugAssert(m_cell != NULL);
|
||||
}
|
||||
|
||||
// Advance until we have a value that can be returned, either
|
||||
// because we don't care about exactness or because it is
|
||||
// guaranteed to be within the box.
|
||||
} while (m_exact && ! m_box.contains(position()));
|
||||
}
|
||||
|
||||
|
||||
/** End iterator */
|
||||
BoxIterator() : m_isEnd(true), m_grid(NULL), m_exact(true), m_current(0,0,0), m_cell(NULL), m_arrayIndex(0), m_epoch(0) {}
|
||||
|
||||
/** Begin iterator */
|
||||
BoxIterator(const ThisType* grid, bool exact, const AABox& box) :
|
||||
m_isEnd(false),
|
||||
m_grid(grid),
|
||||
m_exact(exact),
|
||||
m_box(box),
|
||||
m_current(-1, 0 ,0),
|
||||
m_cell(NULL),
|
||||
m_arrayIndex(0),
|
||||
m_epoch(grid->m_epoch) {
|
||||
|
||||
m_grid->getCellCoord(box.low(), m_lo);
|
||||
m_grid->getCellCoord(box.high(), m_hi);
|
||||
|
||||
// Get to the first value
|
||||
m_current = m_lo;
|
||||
// Back up one so that advancing takes us to the first
|
||||
--m_current.x;
|
||||
advance();
|
||||
}
|
||||
|
||||
const Value& value() const {
|
||||
debugAssert(! m_isEnd);
|
||||
return (*m_cell)[m_arrayIndex].value;
|
||||
}
|
||||
|
||||
/** Used by SphereIterator::advance() */
|
||||
const Vector3& position() const {
|
||||
debugAssert(! m_isEnd);
|
||||
return (*m_cell)[m_arrayIndex].position;
|
||||
}
|
||||
|
||||
// Intentionally unimplemented
|
||||
BoxIterator& operator=(const BoxIterator&);
|
||||
|
||||
public:
|
||||
|
||||
inline bool operator!=(const BoxIterator& other) const {
|
||||
if (other.m_isEnd && m_isEnd) {
|
||||
return false;
|
||||
} else {
|
||||
return (m_isEnd != other.m_isEnd) ||
|
||||
(m_cell != other.m_cell) ||
|
||||
(m_arrayIndex != other.m_arrayIndex);
|
||||
}
|
||||
}
|
||||
|
||||
bool operator==(const BoxIterator& other) const {
|
||||
return !(*this != other);
|
||||
}
|
||||
|
||||
/** Preincrement */
|
||||
BoxIterator& operator++() {
|
||||
debugAssert(! m_isEnd);
|
||||
debugAssertM(m_epoch == m_grid->m_epoch,
|
||||
"It is illegal to mutate the HashGrid "
|
||||
"while iterating through it.");
|
||||
|
||||
advance();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Post increment (slower) */
|
||||
BoxIterator operator++(int) {
|
||||
Iterator old = *this;
|
||||
++(*this);
|
||||
return old;
|
||||
}
|
||||
|
||||
const Value& operator*() const { return value(); }
|
||||
const Value* operator->() const { return &value(); }
|
||||
operator Value*() const { return &value(); }
|
||||
|
||||
bool hasMore() const {
|
||||
return ! m_isEnd;
|
||||
}
|
||||
}; // BoxIterator
|
||||
|
||||
/**
|
||||
Finds all values whose positions are within @a box. It is an error to
|
||||
mutate the PointHashGrid while iterating through it.
|
||||
|
||||
@param exact If false, the iterator will execute more quickly but will likely return some
|
||||
values that lie outside the box. Set exact = false if you are going to test the
|
||||
results against the yourself box anyway.
|
||||
*/
|
||||
BoxIterator beginBoxIntersection(const AABox& box, bool exact = true) const {
|
||||
return BoxIterator(this, exact, box);
|
||||
}
|
||||
|
||||
const BoxIterator& endBoxIntersection() const {
|
||||
static const BoxIterator it;
|
||||
return it;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class SphereIterator {
|
||||
private:
|
||||
|
||||
friend class ThisType;
|
||||
|
||||
bool m_isEnd;
|
||||
Sphere m_sphere;
|
||||
BoxIterator m_boxIterator;
|
||||
|
||||
SphereIterator() : m_isEnd(true) {}
|
||||
|
||||
void advance() {
|
||||
if (! m_boxIterator.hasMore()) {
|
||||
m_isEnd = true;
|
||||
return;
|
||||
}
|
||||
|
||||
while (! m_sphere.contains(m_boxIterator.position())) {
|
||||
++m_boxIterator;
|
||||
|
||||
if (! m_boxIterator.hasMore()) {
|
||||
m_isEnd = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static AABox getBoundingBox(const Sphere& s) {
|
||||
AABox box;
|
||||
s.getBounds(box);
|
||||
return box;
|
||||
}
|
||||
|
||||
SphereIterator(const ThisType* grid, const Sphere& sphere) :
|
||||
m_isEnd(false),
|
||||
m_sphere(sphere),
|
||||
m_boxIterator(grid, false, getBoundingBox(sphere)) {
|
||||
|
||||
// Find the first element that is actually in the sphere,
|
||||
// not just the box.
|
||||
advance();
|
||||
}
|
||||
|
||||
const Value& value() const {
|
||||
return *m_boxIterator;
|
||||
}
|
||||
|
||||
// TODO: if the sphere is very big compared to radius, check each
|
||||
// cell's box to see if the cell itself is actually inside the sphere
|
||||
// before iterating through it, since there may be many boxes outside the sphere.
|
||||
|
||||
// Intentionally unimplemented
|
||||
SphereIterator& operator=(const SphereIterator&);
|
||||
public:
|
||||
|
||||
inline bool operator!=(const SphereIterator& other) const {
|
||||
if (other.m_isEnd && m_isEnd) {
|
||||
return false;
|
||||
} else {
|
||||
return
|
||||
(m_isEnd != other.m_isEnd) ||
|
||||
(m_sphere != other.m_sphere) ||
|
||||
(m_boxIterator != other.m_boxIterator);
|
||||
}
|
||||
}
|
||||
|
||||
bool operator==(const SphereIterator& other) const {
|
||||
return !(*this != other);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Preincrement */
|
||||
SphereIterator& operator++() {
|
||||
debugAssert(! m_isEnd);
|
||||
|
||||
++m_boxIterator;
|
||||
advance();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Post increment (slower) */
|
||||
SphereIterator operator++(int) {
|
||||
Iterator old = *this;
|
||||
++(*this);
|
||||
return old;
|
||||
}
|
||||
|
||||
const Value& operator*() const { return value(); }
|
||||
const Value* operator->() const { return &value(); }
|
||||
operator Value*() const { return &value(); }
|
||||
|
||||
bool hasMore() const {
|
||||
return ! m_isEnd;
|
||||
}
|
||||
}; // SphereIterator
|
||||
|
||||
/**
|
||||
Finds all values whose positions are within @a sphere. It is an error
|
||||
to mutate the HashGrid while iterating through it.
|
||||
*/
|
||||
SphereIterator beginSphereIntersection(const Sphere& sphere) const {
|
||||
return SphereIterator(this, sphere);
|
||||
}
|
||||
|
||||
const SphereIterator& endSphereIntersection() const {
|
||||
static const SphereIterator it;
|
||||
return it;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
Dereference to access the bounds() and size() [element count] of the underlying
|
||||
cell objet.
|
||||
|
||||
Example:
|
||||
<pre>
|
||||
for(PointHashGrid<Vector3>::CellIterator iter = grid.beginCells(); iter != grid.endCells(); ++iter) {
|
||||
entriesFound += iter->size();
|
||||
}
|
||||
</pre>
|
||||
*/
|
||||
class CellIterator {
|
||||
private:
|
||||
friend class ThisType;
|
||||
|
||||
bool m_isEnd;
|
||||
const ThisType* m_grid;
|
||||
typename CellTable::Iterator m_tableIterator;
|
||||
const int m_epoch;
|
||||
|
||||
|
||||
Cell& cell() {
|
||||
return m_tableIterator->value;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
class CellObject {
|
||||
friend class CellIterator;
|
||||
private:
|
||||
const CellIterator* m_parent;
|
||||
|
||||
CellObject() : m_parent(NULL) {}
|
||||
|
||||
public:
|
||||
|
||||
/** Returns the bounds on this cell */
|
||||
AABox bounds() const {
|
||||
const Vector3int32& k = m_parent->m_tableIterator->key;
|
||||
return AABox(Vector3(k) * m_parent->m_cellWidth,
|
||||
Vector3(k + Vector3int32(1, 1, 1)) * m_parent->m_cellWidth);
|
||||
}
|
||||
|
||||
/** Number of elements inside this cell */
|
||||
int size() const {
|
||||
debugAssert(! m_parent->m_isEnd);
|
||||
return m_parent->m_tableIterator->value.size();
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
/** Used to make the indirection work.*/
|
||||
CellObject m_indirection;
|
||||
|
||||
/** End iterator. Note that the m_tableIterator is initialized to the end iterator
|
||||
of a temporary value! This is ok because we'll never look at the value of the
|
||||
m_tableIterator, since we're initializing the "end" Iterator.*/
|
||||
CellIterator() :
|
||||
m_isEnd(true),
|
||||
m_grid(NULL),
|
||||
m_tableIterator( CellTable().end() ),
|
||||
m_epoch(0) {}
|
||||
|
||||
CellIterator(const ThisType* grid) :
|
||||
m_isEnd(false),
|
||||
m_grid(grid),
|
||||
m_tableIterator( grid->m_data.begin()),
|
||||
m_epoch(grid->m_epoch) {
|
||||
m_indirection.m_parent = this;
|
||||
m_isEnd = ! m_tableIterator.hasMore();
|
||||
}
|
||||
|
||||
// Intentionally unimplemented
|
||||
CellIterator& operator=(const CellIterator&);
|
||||
|
||||
public:
|
||||
|
||||
const CellObject& operator*() const { return m_indirection; }
|
||||
const CellObject* operator->() const { return &m_indirection; }
|
||||
operator CellObject*() const { return &m_indirection; }
|
||||
|
||||
inline bool operator!=(const CellIterator& other) const {
|
||||
// != is called more often than == during iteration
|
||||
return !(
|
||||
(m_isEnd && other.m_isEnd) ||
|
||||
((m_isEnd == other.m_isEnd) &&
|
||||
(m_tableIterator != other.m_tableIterator)));
|
||||
}
|
||||
|
||||
bool operator==(const CellIterator& other) const {
|
||||
return !(*this != other);
|
||||
}
|
||||
|
||||
/** Preincrement */
|
||||
CellIterator& operator++() {
|
||||
debugAssertM(m_epoch == m_grid->m_epoch,
|
||||
"It is illegal to mutate the HashGrid while "
|
||||
"iterating through it.");
|
||||
++m_tableIterator;
|
||||
m_isEnd = ! m_tableIterator.hasMore();
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Post increment (slower) */
|
||||
CellIterator operator++(int) {
|
||||
Iterator old = *this;
|
||||
++(*this);
|
||||
return old;
|
||||
}
|
||||
|
||||
bool hasMore() const {
|
||||
return ! m_isEnd;
|
||||
}
|
||||
}; // CellIterator
|
||||
|
||||
/** Iterates through the non-empty cells. This is intended primarily for
|
||||
debugging and visualizing the data structure.*/
|
||||
CellIterator beginCells() const {
|
||||
return CellIterator(this);
|
||||
}
|
||||
|
||||
const CellIterator& endCells() const {
|
||||
static const CellIterator it;
|
||||
return it;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/** Returns true if there is a value that is exactly equal to @a v. This will
|
||||
check all neighboring cells to avoid roundoff error at cell boundaries.
|
||||
*/
|
||||
bool contains(const Value& v) const {
|
||||
Cell* cell = NULL;
|
||||
int index = 0;
|
||||
Vector3int32 cellCoord;
|
||||
return const_cast<ThisType*>(this)->find(v, cellCoord, cell, index);
|
||||
}
|
||||
|
||||
/** Calls delete on all of the values, which are assumed to be pointers.
|
||||
This is a helper to avoid requiring you to iterate through the data
|
||||
structure, removing and deleting each one. Clears the PointHashGrid at the
|
||||
end.
|
||||
|
||||
Using objects (instead of pointers) or reference counted pointers is
|
||||
recommended over using pointers and this deleteAll method.*/
|
||||
void deleteAll() {
|
||||
for (Iterator it = begin(); it.hasMore(); ++it) {
|
||||
delete *it;
|
||||
}
|
||||
clear();
|
||||
}
|
||||
|
||||
void clearAndSetMemoryManager(const MemoryManager::Ref& m) {
|
||||
++m_epoch;
|
||||
m_size = 0;
|
||||
m_bounds = AABox();
|
||||
|
||||
m_data.clearAndSetMemoryManager(m);
|
||||
m_memoryManager = m;
|
||||
}
|
||||
|
||||
/** Removes all data.
|
||||
@param shrink If true, underlying structures are deallocated as
|
||||
they are freed.*/
|
||||
void clear(bool shrink = true) {
|
||||
m_size = 0;
|
||||
m_bounds = AABox();
|
||||
if (! shrink) {
|
||||
// Remove all data
|
||||
for (CellIterator it = beginCells(); it.hasMore(); ++it) {
|
||||
it.cell().clear(true);
|
||||
}
|
||||
} else {
|
||||
m_data.clear();
|
||||
}
|
||||
++m_epoch;
|
||||
}
|
||||
|
||||
int debugGetDeepestBucketSize() const {
|
||||
return m_data.debugGetDeepestBucketSize();
|
||||
}
|
||||
|
||||
float debugGetAverageBucketSize() const {
|
||||
return m_data.debugGetAverageBucketSize();
|
||||
}
|
||||
#undef ThisType
|
||||
};
|
||||
|
||||
} // G3D
|
||||
#endif
|
||||
1185
dep/include/g3dlite/G3D/PointKDTree.h
Normal file
1185
dep/include/g3dlite/G3D/PointKDTree.h
Normal file
File diff suppressed because it is too large
Load diff
292
dep/include/g3dlite/G3D/Pointer.h
Normal file
292
dep/include/g3dlite/G3D/Pointer.h
Normal file
|
|
@ -0,0 +1,292 @@
|
|||
/**
|
||||
@file Pointer.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2007-05-16
|
||||
@edited 2009-03-26
|
||||
|
||||
Copyright 2000-2009, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
#ifndef G3D_Pointer_h
|
||||
#define G3D_Pointer_h
|
||||
|
||||
#include "G3D/debugAssert.h"
|
||||
#include "G3D/ReferenceCount.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
Acts like a pointer to a value of type ValueType (i.e.,
|
||||
ValueType*), but can operate through accessor methods as well as on
|
||||
a value in memory. This is useful for implementing scripting
|
||||
languages and other applications that need to connect existing APIs
|
||||
by reference.
|
||||
|
||||
Because the accessors require values to be passed by value (instead of by reference)
|
||||
this is primarily useful for objects whose memory size is small.
|
||||
|
||||
<pre>
|
||||
class Foo {
|
||||
public:
|
||||
void setEnabled(bool b);
|
||||
bool getEnabled() const;
|
||||
};
|
||||
|
||||
Foo f;
|
||||
bool b;
|
||||
|
||||
Pointer<bool> p1(&b);
|
||||
Pointer<bool> p2(&f, &Foo::getEnabled, &Foo::setEnabled);
|
||||
|
||||
*p1 = true;
|
||||
*p2 = false;
|
||||
*p2 = *p1; \/\/ Value assignment
|
||||
p2 = p1; \/\/ Pointer aliasing
|
||||
|
||||
\/\/ Or, equivalently:
|
||||
p1.setValue(true);
|
||||
p2.setValue(false);
|
||||
|
||||
p2.setValue(p1.getValue());
|
||||
p2 = p1;
|
||||
</pre>
|
||||
|
||||
<i>Note:</i> Because of the way that dereference is implemented, you cannot pass <code>*p</code> through a function
|
||||
that takes varargs (...), e.g., <code>printf("%d", *p)</code> will produce a compile-time error. Instead use
|
||||
<code>printf("%d",(bool)*p)</code> or <code>printf("%d", p.getValue())</code>.
|
||||
|
||||
*/
|
||||
template<class ValueType>
|
||||
class Pointer {
|
||||
private:
|
||||
|
||||
class Interface {
|
||||
public:
|
||||
virtual ~Interface() {};
|
||||
virtual void set(ValueType b) = 0;
|
||||
virtual ValueType get() const = 0;
|
||||
virtual Interface* clone() const = 0;
|
||||
virtual bool isNull() const = 0;
|
||||
};
|
||||
|
||||
class Memory : public Interface {
|
||||
private:
|
||||
|
||||
ValueType* value;
|
||||
|
||||
public:
|
||||
|
||||
Memory(ValueType* value) : value(value) {
|
||||
//debugAssert(value != NULL);
|
||||
}
|
||||
|
||||
virtual void set(ValueType v) {
|
||||
*value = v;
|
||||
}
|
||||
|
||||
virtual ValueType get() const {
|
||||
return *value;
|
||||
}
|
||||
|
||||
virtual Interface* clone() const {
|
||||
return new Memory(value);
|
||||
}
|
||||
|
||||
virtual bool isNull() const {
|
||||
return value == NULL;
|
||||
}
|
||||
};
|
||||
|
||||
template<class T, typename GetMethod, typename SetMethod>
|
||||
class Accessor : public Interface {
|
||||
private:
|
||||
|
||||
T* object;
|
||||
GetMethod getMethod;
|
||||
SetMethod setMethod;
|
||||
|
||||
public:
|
||||
|
||||
Accessor(T* object,
|
||||
GetMethod getMethod,
|
||||
SetMethod setMethod) : object(object), getMethod(getMethod), setMethod(setMethod) {
|
||||
debugAssert(object != NULL);
|
||||
}
|
||||
|
||||
virtual void set(ValueType v) {
|
||||
(object->*setMethod)(v);
|
||||
}
|
||||
|
||||
virtual ValueType get() const {
|
||||
return (object->*getMethod)();
|
||||
}
|
||||
|
||||
virtual Interface* clone() const {
|
||||
return new Accessor(object, getMethod, setMethod);
|
||||
}
|
||||
|
||||
virtual bool isNull() const {
|
||||
return object == NULL;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<class T, typename GetMethod, typename SetMethod>
|
||||
class RefAccessor : public Interface {
|
||||
private:
|
||||
|
||||
ReferenceCountedPointer<T> object;
|
||||
GetMethod getMethod;
|
||||
SetMethod setMethod;
|
||||
|
||||
public:
|
||||
|
||||
RefAccessor(
|
||||
const ReferenceCountedPointer<T>& object,
|
||||
GetMethod getMethod,
|
||||
SetMethod setMethod) : object(object), getMethod(getMethod), setMethod(setMethod) {
|
||||
|
||||
debugAssert(object != NULL);
|
||||
}
|
||||
|
||||
virtual void set(ValueType v) {
|
||||
(object.pointer()->*setMethod)(v);
|
||||
}
|
||||
|
||||
virtual ValueType get() const {
|
||||
return (object.pointer()->*getMethod)();
|
||||
}
|
||||
|
||||
virtual Interface* clone() const {
|
||||
return new RefAccessor(object, getMethod, setMethod);
|
||||
}
|
||||
|
||||
virtual bool isNull() const {
|
||||
return object.isNull();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Interface* m_interface;
|
||||
|
||||
public:
|
||||
|
||||
Pointer() : m_interface(NULL) {};
|
||||
|
||||
/** Allows implicit cast from real pointer */
|
||||
Pointer(ValueType* v) : m_interface(new Memory(v)) {}
|
||||
|
||||
inline bool isNull() const {
|
||||
return (m_interface == NULL) || m_interface->isNull();
|
||||
}
|
||||
|
||||
// Assignment
|
||||
inline Pointer& operator=(const Pointer& r) {
|
||||
delete m_interface;
|
||||
if (r.m_interface != NULL) {
|
||||
m_interface = r.m_interface->clone();
|
||||
} else {
|
||||
m_interface = NULL;
|
||||
}
|
||||
return this[0];
|
||||
}
|
||||
|
||||
Pointer(const Pointer& p) : m_interface(NULL) {
|
||||
this[0] = p;
|
||||
}
|
||||
|
||||
template<class Class>
|
||||
Pointer(const ReferenceCountedPointer<Class>& object,
|
||||
ValueType (Class::*getMethod)() const,
|
||||
void (Class::*setMethod)(ValueType)) :
|
||||
m_interface(new RefAccessor<Class, ValueType (Class::*)() const, void (Class::*)(ValueType)>(object, getMethod, setMethod)) {}
|
||||
|
||||
template<class Class>
|
||||
Pointer(const ReferenceCountedPointer<Class>& object,
|
||||
const ValueType& (Class::*getMethod)() const,
|
||||
void (Class::*setMethod)(ValueType)) :
|
||||
m_interface(new RefAccessor<Class, const ValueType& (Class::*)() const, void (Class::*)(ValueType)>(object, getMethod, setMethod)) {}
|
||||
|
||||
template<class Class>
|
||||
Pointer(const ReferenceCountedPointer<Class>& object,
|
||||
ValueType (Class::*getMethod)() const,
|
||||
void (Class::*setMethod)(const ValueType&)) :
|
||||
m_interface(new RefAccessor<Class, ValueType (Class::*)() const, void (Class::*)(const ValueType&)>(object, getMethod, setMethod)) {}
|
||||
|
||||
template<class Class>
|
||||
Pointer(const ReferenceCountedPointer<Class>& object,
|
||||
const ValueType& (Class::*getMethod)() const,
|
||||
void (Class::*setMethod)(const ValueType&)) :
|
||||
m_interface(new RefAccessor<Class, const ValueType& (Class::*)() const, void (Class::*)(const ValueType&)>(object, getMethod, setMethod)) {}
|
||||
|
||||
template<class Class>
|
||||
Pointer(Class* object,
|
||||
const ValueType& (Class::*getMethod)() const,
|
||||
void (Class::*setMethod)(const ValueType&)) :
|
||||
m_interface(new Accessor<Class, const ValueType& (Class::*)() const, void (Class::*)(const ValueType&)>(object, getMethod, setMethod)) {}
|
||||
|
||||
template<class Class>
|
||||
Pointer(Class* object,
|
||||
ValueType (Class::*getMethod)() const,
|
||||
void (Class::*setMethod)(const ValueType&)) :
|
||||
m_interface(new Accessor<Class, ValueType (Class::*)() const, void (Class::*)(const ValueType&)>(object, getMethod, setMethod)) {}
|
||||
|
||||
template<class Class>
|
||||
Pointer(Class* object,
|
||||
const ValueType& (Class::*getMethod)() const,
|
||||
void (Class::*setMethod)(ValueType)) :
|
||||
m_interface(new Accessor<Class, const ValueType& (Class::*)() const, void (Class::*)(ValueType)>(object, getMethod, setMethod)) {}
|
||||
|
||||
template<class Class>
|
||||
Pointer(Class* object,
|
||||
ValueType (Class::*getMethod)() const,
|
||||
void (Class::*setMethod)(ValueType)) :
|
||||
m_interface(new Accessor<Class, ValueType (Class::*)() const, void (Class::*)(ValueType)>(object, getMethod, setMethod)) {}
|
||||
|
||||
~Pointer() {
|
||||
delete m_interface;
|
||||
}
|
||||
|
||||
inline const ValueType getValue() const {
|
||||
debugAssert(m_interface != NULL);
|
||||
return m_interface->get();
|
||||
}
|
||||
|
||||
inline void setValue(const ValueType& v) {
|
||||
debugAssert(m_interface != NULL);
|
||||
m_interface->set(v);
|
||||
}
|
||||
|
||||
class IndirectValue {
|
||||
private:
|
||||
|
||||
friend class Pointer;
|
||||
Pointer* pointer;
|
||||
IndirectValue(Pointer* p) : pointer(p) {}
|
||||
|
||||
public:
|
||||
|
||||
void operator=(const ValueType& v) {
|
||||
pointer->setValue(v);
|
||||
}
|
||||
|
||||
operator ValueType() const {
|
||||
return pointer->getValue();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
inline IndirectValue operator*() {
|
||||
return IndirectValue(this);
|
||||
}
|
||||
|
||||
inline const ValueType operator*() const {
|
||||
return getValue();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
7
dep/include/g3dlite/G3D/PositionTrait.h
Normal file
7
dep/include/g3dlite/G3D/PositionTrait.h
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
#ifndef G3D_POSITIONTRAIT_H
|
||||
#define G3D_POSITIONTRAIT_H
|
||||
|
||||
template<typename Value>
|
||||
struct PositionTrait{};
|
||||
|
||||
#endif
|
||||
110
dep/include/g3dlite/G3D/PrecomputedRandom.h
Normal file
110
dep/include/g3dlite/G3D/PrecomputedRandom.h
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
/**
|
||||
@file PrecomputedRandom.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2009-03-31
|
||||
@edited 2009-03-31
|
||||
|
||||
Copyright 2000-2009, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
#ifndef G3D_PrecomputedRandom_h
|
||||
#define G3D_PrecomputedRandom_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Random.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/** Fast random numbers using a precomputed data table.
|
||||
|
||||
e.g., generates cosHemi about 13x faster than Random.
|
||||
This is useful for quickly generating seeded random
|
||||
numbers for reproducibility. G3D::Random takes a long
|
||||
time to seed; this is instantaneous (providing the
|
||||
precomputed data is already available.)
|
||||
|
||||
Not threadsafe.*/
|
||||
class PrecomputedRandom : public Random {
|
||||
public:
|
||||
/** Put the cosHemi and the uniform together so that when
|
||||
alternating between them we stay in cache. This is also packed
|
||||
into a good size for SIMD and GPU operations.*/
|
||||
class HemiUniformData {
|
||||
public:
|
||||
float cosHemiX;
|
||||
float cosHemiY;
|
||||
float cosHemiZ;
|
||||
float uniform;
|
||||
};
|
||||
|
||||
class SphereBitsData {
|
||||
public:
|
||||
float sphereX;
|
||||
float sphereY;
|
||||
float sphereZ;
|
||||
uint32 bits;
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
/** Array of 2^n elements. */
|
||||
const HemiUniformData* m_hemiUniform;
|
||||
const SphereBitsData* m_sphereBits;
|
||||
|
||||
/** 2^n - 1; the AND mask for computing a fast modulo */
|
||||
int m_modMask;
|
||||
|
||||
int m_index;
|
||||
|
||||
/** If true, free m_hemiUniform and m_sphereBits in destructor */
|
||||
bool m_freeData;
|
||||
|
||||
public:
|
||||
|
||||
/*
|
||||
\param dataSize Must be a power of 2
|
||||
\param data Will NOT be deleted by the destructor.
|
||||
*/
|
||||
PrecomputedRandom(const HemiUniformData* data1, const SphereBitsData* data2, int dataSize, uint32 seed = 0xF018A4D2);
|
||||
|
||||
/**
|
||||
\param dataSize Number of random numbers that can be requested before periodicity. Must be a power of 2.
|
||||
*/
|
||||
PrecomputedRandom(int dataSize, uint32 seed = 0xF018A4D2);
|
||||
|
||||
~PrecomputedRandom();
|
||||
|
||||
/** Each bit is random. Subclasses can choose to override just
|
||||
this method and the other methods will all work automatically. */
|
||||
virtual uint32 bits();
|
||||
|
||||
// integer is inherited
|
||||
|
||||
/** Uniform random float on the range [min, max] */
|
||||
virtual float uniform(float low, float high);
|
||||
|
||||
/** Uniform random float on the range [0, 1] */
|
||||
virtual float uniform();
|
||||
|
||||
// gaussian is inherited
|
||||
|
||||
/** Returns 3D unit vectors distributed according to
|
||||
a cosine distribution about the z axis. */
|
||||
virtual void cosHemi(float& x, float& y, float& z);
|
||||
|
||||
/** Returns 3D unit vectors distributed according to a cosine
|
||||
power distribution (\f$ \mbox{cos}^k \theta \f$) about
|
||||
the z-axis. */
|
||||
virtual void cosPowHemi(const float k, float& x, float& y, float& z);
|
||||
|
||||
// hemi is inherited
|
||||
|
||||
/** Returns 3D unit vectors uniformly distributed on the sphere */
|
||||
virtual void sphere(float& x, float& y, float& z);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -3,14 +3,14 @@
|
|||
|
||||
Quaternion
|
||||
|
||||
@maintainer Morgan McGuire, matrix@graphics3d.com
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2002-01-23
|
||||
@edited 2006-05-10
|
||||
@edited 2009-05-10
|
||||
*/
|
||||
|
||||
#ifndef G3D_QUAT_H
|
||||
#define G3D_QUAT_H
|
||||
#ifndef G3D_Quat_h
|
||||
#define G3D_Quat_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
|
|
@ -89,10 +89,10 @@ public:
|
|||
}
|
||||
|
||||
/** Note: two quats can represent the Quat::sameRotation and not be equal. */
|
||||
bool fuzzyEq(const Quat& q) {
|
||||
return G3D::fuzzyEq(x, q.x) && G3D::fuzzyEq(y, q.y) && G3D::fuzzyEq(z, q.z) && G3D::fuzzyEq(w, q.w);
|
||||
}
|
||||
|
||||
bool fuzzyEq(const Quat& q) {
|
||||
return G3D::fuzzyEq(x, q.x) && G3D::fuzzyEq(y, q.y) && G3D::fuzzyEq(z, q.z) && G3D::fuzzyEq(w, q.w);
|
||||
}
|
||||
|
||||
/** True if these quaternions represent the same rotation (note that every rotation is
|
||||
represented by two values; q and -q).
|
||||
*/
|
||||
|
|
@ -177,6 +177,14 @@ public:
|
|||
return Quat(x * s, y * s, z * s, w * s);
|
||||
}
|
||||
|
||||
inline Quat& operator*=(float s) {
|
||||
x *= s;
|
||||
y *= s;
|
||||
z *= s;
|
||||
w *= s;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** @cite Based on Watt & Watt, page 360 */
|
||||
friend Quat operator* (float s, const Quat& q);
|
||||
|
||||
|
|
@ -227,7 +235,7 @@ public:
|
|||
} else if (w < 0) {
|
||||
// Log of a negative number. Multivalued, any number of the form
|
||||
// (PI * v, ln(-q.w))
|
||||
return Quat((float)G3D_PI, 0, 0, ::logf(-w));
|
||||
return Quat((float)pi(), 0, 0, ::logf(-w));
|
||||
} else {
|
||||
// log of zero!
|
||||
return Quat((float)nan(), (float)nan(), (float)nan(), (float)nan());
|
||||
|
|
@ -281,17 +289,10 @@ public:
|
|||
return (log() * x).exp();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@deprecated
|
||||
Use toUnit()
|
||||
*/
|
||||
inline Quat unitize() const {
|
||||
inline void unitize() {
|
||||
float mag2 = dot(*this);
|
||||
if (G3D::fuzzyEq(mag2, 1.0f)) {
|
||||
return *this;
|
||||
} else {
|
||||
return *this / sqrtf(mag2);
|
||||
if (! G3D::fuzzyEq(mag2, 1.0f)) {
|
||||
*this *= rsq(mag2);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -300,7 +301,9 @@ public:
|
|||
the magnitude.
|
||||
*/
|
||||
inline Quat toUnit() const {
|
||||
return unitize();
|
||||
Quat x = *this;
|
||||
x.unitize();
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -326,6 +329,9 @@ public:
|
|||
*/
|
||||
static Quat unitRandom();
|
||||
|
||||
void deserialize(class BinaryInput& b);
|
||||
void serialize(class BinaryOutput& b) const;
|
||||
|
||||
// 2-char swizzles
|
||||
|
||||
Vector2 xx() const;
|
||||
|
|
@ -688,6 +694,26 @@ inline G3D::Quat operator*(float s, const G3D::Quat& q) {
|
|||
return q * s;
|
||||
}
|
||||
|
||||
inline float& Quat::operator[] (int i) {
|
||||
debugAssert(i >= 0);
|
||||
debugAssert(i < 4);
|
||||
return ((float*)this)[i];
|
||||
}
|
||||
|
||||
inline const float& Quat::operator[] (int i) const {
|
||||
debugAssert(i >= 0);
|
||||
debugAssert(i < 4);
|
||||
return ((float*)this)[i];
|
||||
}
|
||||
|
||||
inline Quat Quat::operator-(const Quat& other) const {
|
||||
return Quat(x - other.x, y - other.y, z - other.z, w - other.w);
|
||||
}
|
||||
|
||||
inline Quat Quat::operator+(const Quat& other) const {
|
||||
return Quat(x + other.x, y + other.y, z + other.z, w + other.w);
|
||||
}
|
||||
|
||||
} // Namespace G3D
|
||||
|
||||
// Outside the namespace to avoid overloading confusion for C++
|
||||
|
|
@ -696,7 +722,4 @@ inline G3D::Quat pow(const G3D::Quat& q, double x) {
|
|||
}
|
||||
|
||||
|
||||
|
||||
#include "Quat.inl"
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,38 +0,0 @@
|
|||
/**
|
||||
Quat.inl
|
||||
|
||||
@cite Quaternion implementation based on Watt & Watt page 363.
|
||||
Thanks to Max McGuire for slerp optimizations.
|
||||
|
||||
@maintainer Morgan McGuire, matrix@graphics3d.com
|
||||
|
||||
@created 2002-01-23
|
||||
@edited 2004-03-04
|
||||
*/
|
||||
|
||||
namespace G3D {
|
||||
|
||||
inline float& Quat::operator[] (int i) {
|
||||
debugAssert(i >= 0);
|
||||
debugAssert(i < 4);
|
||||
return ((float*)this)[i];
|
||||
}
|
||||
|
||||
inline const float& Quat::operator[] (int i) const {
|
||||
debugAssert(i >= 0);
|
||||
debugAssert(i < 4);
|
||||
return ((float*)this)[i];
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Quat Quat::operator-(const Quat& other) const {
|
||||
return Quat(x - other.x, y - other.y, z - other.z, w - other.w);
|
||||
}
|
||||
|
||||
inline Quat Quat::operator+(const Quat& other) const {
|
||||
return Quat(x + other.x, y + other.y, z + other.z, w + other.w);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
364
dep/include/g3dlite/G3D/Queue.h
Normal file
364
dep/include/g3dlite/G3D/Queue.h
Normal file
|
|
@ -0,0 +1,364 @@
|
|||
/**
|
||||
@file Queue.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2002-07-09
|
||||
@edited 2008-12-20
|
||||
*/
|
||||
|
||||
#ifndef G3D_QUEUE_H
|
||||
#define G3D_QUEUE_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/System.h"
|
||||
#include "G3D/debug.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
Locate the indices of the break between of the two
|
||||
sections of the circular queue. These are used to
|
||||
construct two for loops that iterate over the whole
|
||||
sequence without using the modulo operator.
|
||||
|
||||
[0 ... secondEnd) [head .... firstEnd)
|
||||
*/
|
||||
#define FIND_ENDS \
|
||||
int firstEnd = head + num;\
|
||||
int secondEnd = 0;\
|
||||
if (firstEnd > numAllocated) {\
|
||||
secondEnd = firstEnd - numAllocated;\
|
||||
firstEnd = numAllocated;\
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Dynamic queue that uses a circular buffer for performance.
|
||||
|
||||
Faster than std::deque for objects with constructors.
|
||||
*/
|
||||
template <class T>
|
||||
class Queue {
|
||||
private:
|
||||
//
|
||||
// |<---- num ---->|
|
||||
// [ | | | | | | | | | | | | | ]
|
||||
// ^
|
||||
// |
|
||||
// head
|
||||
//
|
||||
//
|
||||
|
||||
/**
|
||||
Only num elements are initialized.
|
||||
*/
|
||||
T* data;
|
||||
|
||||
/**
|
||||
Index of the next element to be dequeue-d in data.
|
||||
*/
|
||||
int head;
|
||||
|
||||
/**
|
||||
Number of elements (including head) that are visible and initialized.
|
||||
*/
|
||||
int num;
|
||||
|
||||
/**
|
||||
Size of data array in elements.
|
||||
*/
|
||||
int numAllocated;
|
||||
|
||||
/** If a clear was needed, assumes it already occured */
|
||||
void _copy(const Queue& other) {
|
||||
debugAssert(data == NULL);
|
||||
data = (T*)System::malloc(sizeof(T) * other.numAllocated);
|
||||
debugAssert(data);
|
||||
head = other.head;
|
||||
num = other.num;
|
||||
numAllocated = other.numAllocated;
|
||||
|
||||
FIND_ENDS;
|
||||
|
||||
for (int i = head; i < firstEnd; ++i) {
|
||||
new (data + i)T(other.data[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < secondEnd; ++i) {
|
||||
new (data + i)T(other.data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Computes a data array index from a queue position. The queue position
|
||||
may be negative.
|
||||
*/
|
||||
inline int index(int i) const {
|
||||
return (head + i + numAllocated) % numAllocated;
|
||||
}
|
||||
|
||||
/**
|
||||
Allocates newSize elements and repacks the array.
|
||||
*/
|
||||
void repackAndRealloc(int newSize) {
|
||||
// TODO: shrink queue
|
||||
T* old = data;
|
||||
data = (T*)System::malloc(newSize * sizeof(T));
|
||||
debugAssert(data != NULL);
|
||||
|
||||
FIND_ENDS;
|
||||
|
||||
int j = 0;
|
||||
for (int i = head; i < firstEnd; ++i, ++j) {
|
||||
new (data + j)T(old[i]);
|
||||
(old + i)->~T();
|
||||
}
|
||||
|
||||
for (int i = 0; i < secondEnd; ++i, ++j) {
|
||||
new (data + j)T(old[i]);
|
||||
(old + i)->~T();
|
||||
}
|
||||
|
||||
head = 0;
|
||||
System::free(old);
|
||||
numAllocated = newSize;
|
||||
}
|
||||
|
||||
/**
|
||||
Ensure that there is at least one element between
|
||||
the tail and head, wrapping around in the circular
|
||||
buffer.
|
||||
*/
|
||||
inline void reserveSpace() {
|
||||
if (num == numAllocated) {
|
||||
repackAndRealloc(numAllocated * 3 + 20);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Queue() :
|
||||
data(NULL),
|
||||
head(0),
|
||||
num(0),
|
||||
numAllocated(0) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Copy constructor
|
||||
*/
|
||||
Queue(const Queue& other) : data(NULL) {
|
||||
_copy(other);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Destructor does not delete() the objects if T is a pointer type
|
||||
(e.g. T = int*) instead, it deletes the pointers themselves and
|
||||
leaves the objects. Call deleteAll if you want to dealocate
|
||||
the objects referenced.
|
||||
*/
|
||||
virtual ~Queue() {
|
||||
clear();
|
||||
}
|
||||
|
||||
/**
|
||||
Insert a new element into the front of the queue
|
||||
(a traditional queue only uses pushBack).
|
||||
*/
|
||||
inline void pushFront(const T& e) {
|
||||
reserveSpace();
|
||||
|
||||
// Get the index of head-1
|
||||
int i = index(-1);
|
||||
|
||||
// Call the constructor on the newly exposed element.
|
||||
new (data + i)T(e);
|
||||
|
||||
// Reassign the head to point to this index
|
||||
head = i;
|
||||
++num;
|
||||
}
|
||||
|
||||
/**
|
||||
Insert a new element at the end of the queue.
|
||||
*/
|
||||
inline void pushBack(const T& e) {
|
||||
reserveSpace();
|
||||
|
||||
// Get the index of 1+tail
|
||||
int i = index(num);
|
||||
|
||||
// Initialize that element
|
||||
new (data + i)T(e);
|
||||
++num;
|
||||
}
|
||||
|
||||
/**
|
||||
pushBack
|
||||
*/
|
||||
inline void enqueue(const T& e) {
|
||||
pushBack(e);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Remove the last element from the queue. The queue will never
|
||||
shrink in size. (A typical queue only uses popFront).
|
||||
*/
|
||||
inline T popBack() {
|
||||
int tail = index(num - 1);
|
||||
T result(data[tail]);
|
||||
|
||||
// Call the destructor
|
||||
(data + tail)->~T();
|
||||
--num;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
Remove the next element from the head of the queue. The queue will never
|
||||
shrink in size. */
|
||||
inline T popFront() {
|
||||
T result(data[head]);
|
||||
// Call the destructor
|
||||
(data + head)->~T();
|
||||
head = (head + 1) % numAllocated;
|
||||
--num;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
popFront
|
||||
*/
|
||||
inline T dequeue() {
|
||||
return popFront();
|
||||
}
|
||||
|
||||
/**
|
||||
Removes all elements (invoking their destructors).
|
||||
|
||||
@param freeStorage If false, the underlying array is not deallocated
|
||||
(allowing fast push in the future), however, the size of the Queue
|
||||
is reported as zero.
|
||||
|
||||
*/
|
||||
void clear(bool freeStorage = true) {
|
||||
|
||||
FIND_ENDS;
|
||||
|
||||
// Invoke the destructors on the elements
|
||||
int i;
|
||||
for (i = head; i < firstEnd; ++i) {
|
||||
(data + i)->~T();
|
||||
}
|
||||
|
||||
for (i = 0; i < secondEnd; ++i) {
|
||||
(data + i)->~T();
|
||||
}
|
||||
|
||||
num = 0;
|
||||
head = 0;
|
||||
if (freeStorage) {
|
||||
numAllocated = 0;
|
||||
System::free(data);
|
||||
data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/** Clear without freeing the underlying array. */
|
||||
void fastClear() {
|
||||
clear(false);
|
||||
}
|
||||
|
||||
/**
|
||||
Assignment operator.
|
||||
*/
|
||||
Queue& operator=(const Queue& other) {
|
||||
clear();
|
||||
_copy(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
Number of elements in the queue.
|
||||
*/
|
||||
inline int size() const {
|
||||
return num;
|
||||
}
|
||||
|
||||
/**
|
||||
Number of elements in the queue.
|
||||
*/
|
||||
inline int length() const {
|
||||
return size();
|
||||
}
|
||||
|
||||
/**
|
||||
Performs bounds checks in debug mode
|
||||
*/
|
||||
inline T& operator[](int n) {
|
||||
debugAssert((n >= 0) && (n < num));
|
||||
return data[index(n)];
|
||||
}
|
||||
|
||||
/**
|
||||
Performs bounds checks in debug mode
|
||||
*/
|
||||
inline const T& operator[](int n) const {
|
||||
debugAssert((n >= 0) && (n < num));
|
||||
return data[index(n)];
|
||||
}
|
||||
|
||||
|
||||
/** Returns the back element */
|
||||
inline const T& last() const {
|
||||
return (*this)[size() - 1];
|
||||
}
|
||||
|
||||
inline T& last() {
|
||||
return (*this)[size() - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
Returns true if the given element is in the queue.
|
||||
*/
|
||||
bool contains(const T& e) const {
|
||||
for (int i = 0; i < size(); ++i) {
|
||||
if ((*this)[i] == e) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
Calls delete on all objects[0...size-1]
|
||||
and sets the queue size to zero.
|
||||
*/
|
||||
void deleteAll() {
|
||||
FIND_ENDS;
|
||||
|
||||
int i;
|
||||
for (i = 0; i < secondEnd; ++i) {
|
||||
delete data[i];
|
||||
}
|
||||
|
||||
for (i = head; i < firstEnd; ++i) {
|
||||
delete data[i];
|
||||
}
|
||||
clear();
|
||||
}
|
||||
};
|
||||
|
||||
#undef FIND_ENDS
|
||||
|
||||
}; // namespace
|
||||
|
||||
#endif
|
||||
139
dep/include/g3dlite/G3D/Random.h
Normal file
139
dep/include/g3dlite/G3D/Random.h
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
/**
|
||||
@file Random.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2009-01-02
|
||||
@edited 2009-03-20
|
||||
|
||||
Copyright 2000-2009, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
#ifndef G3D_Random_h
|
||||
#define G3D_Random_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/GMutex.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/** Random number generator.
|
||||
|
||||
Threadsafe.
|
||||
|
||||
Useful for generating consistent random numbers across platforms
|
||||
and when multiple threads are involved.
|
||||
|
||||
Uses the Fast Mersenne Twister (FMT-19937) algorithm.
|
||||
|
||||
On average, uniform() runs about 2x-3x faster than rand().
|
||||
|
||||
@cite http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html
|
||||
|
||||
On OS X, Random is about 10x faster than drand48() (which is
|
||||
threadsafe) and 4x faster than rand() (which is not threadsafe).
|
||||
*/
|
||||
class Random {
|
||||
protected:
|
||||
|
||||
/** Constants (important for the algorithm; do not modify) */
|
||||
enum {
|
||||
N = 624,
|
||||
M = 397,
|
||||
R = 31,
|
||||
U = 11,
|
||||
S = 7,
|
||||
T = 15,
|
||||
L = 18,
|
||||
A = 0x9908B0DF,
|
||||
B = 0x9D2C5680,
|
||||
C = 0xEFC60000};
|
||||
|
||||
/**
|
||||
Prevents multiple overlapping calls to generate().
|
||||
*/
|
||||
Spinlock lock;
|
||||
|
||||
/** State vector (these are the next N values that will be returned) */
|
||||
uint32* state;
|
||||
|
||||
/** Index into state */
|
||||
int index;
|
||||
|
||||
bool m_threadsafe;
|
||||
|
||||
/** Generate the next N ints, and store them for readback later.
|
||||
Called from bits() */
|
||||
virtual void generate();
|
||||
|
||||
/** For subclasses. The void* parameter is just to distinguish this from the
|
||||
public constructor.*/
|
||||
Random(void*);
|
||||
|
||||
public:
|
||||
|
||||
/** \param threadsafe Set to false if you know that this random
|
||||
will only be used on a single thread. This eliminates the
|
||||
lock and improves performance on some platforms.
|
||||
*/
|
||||
Random(uint32 seed = 0xF018A4D2, bool threadsafe = true);
|
||||
|
||||
virtual ~Random();
|
||||
|
||||
/** Each bit is random. Subclasses can choose to override just
|
||||
this method and the other methods will all work automatically. */
|
||||
virtual uint32 bits();
|
||||
|
||||
/** Uniform random integer on the range [min, max] */
|
||||
virtual int integer(int min, int max);
|
||||
|
||||
/** Uniform random float on the range [min, max] */
|
||||
virtual inline float uniform(float low, float high) {
|
||||
// We could compute the ratio in double precision here for
|
||||
// about 1.5x slower performance and slightly better
|
||||
// precision.
|
||||
return low + (high - low) * ((float)bits() / (float)0xFFFFFFFFUL);
|
||||
}
|
||||
|
||||
/** Uniform random float on the range [0, 1] */
|
||||
virtual inline float uniform() {
|
||||
// We could compute the ratio in double precision here for
|
||||
// about 1.5x slower performance and slightly better
|
||||
// precision.
|
||||
const float norm = 1.0f / (float)0xFFFFFFFFUL;
|
||||
return (float)bits() * norm;
|
||||
}
|
||||
|
||||
/** Normally distributed reals. */
|
||||
virtual float gaussian(float mean, float stdev);
|
||||
|
||||
/** Returns 3D unit vectors distributed according to
|
||||
a cosine distribution about the z-axis. */
|
||||
virtual void cosHemi(float& x, float& y, float& z);
|
||||
|
||||
/** Returns 3D unit vectors distributed according to a cosine
|
||||
power distribution (\f$ \cos^k \theta \f$) about
|
||||
the z-axis. */
|
||||
virtual void cosPowHemi(const float k, float& x, float& y, float& z);
|
||||
|
||||
/** Returns 3D unit vectors uniformly distributed on the
|
||||
hemisphere about the z-axis. */
|
||||
virtual void hemi(float& x, float& y, float& z);
|
||||
|
||||
/** Returns 3D unit vectors uniformly distributed on the sphere */
|
||||
virtual void sphere(float& x, float& y, float& z);
|
||||
|
||||
/**
|
||||
A shared instance for when the performance and features but not
|
||||
consistency of the class are desired. It is slightly (10%)
|
||||
faster to use a distinct instance than to use the common one.
|
||||
|
||||
Threadsafe.
|
||||
*/
|
||||
static Random& common();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -3,14 +3,14 @@
|
|||
|
||||
Ray class
|
||||
|
||||
@maintainer Morgan McGuire, matrix@graphics3d.com
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2002-07-12
|
||||
@edited 2006-02-21
|
||||
@edited 2009-06-29
|
||||
*/
|
||||
|
||||
#ifndef G3D_RAY_H
|
||||
#define G3D_RAY_H
|
||||
#ifndef G3D_Ray_h
|
||||
#define G3D_Ray_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Vector3.h"
|
||||
|
|
@ -23,43 +23,85 @@ namespace G3D {
|
|||
*/
|
||||
class Ray {
|
||||
private:
|
||||
Ray(const Vector3& origin, const Vector3& direction) {
|
||||
this->origin = origin;
|
||||
this->direction = direction;
|
||||
}
|
||||
friend class Intersect;
|
||||
|
||||
Vector3 m_origin;
|
||||
|
||||
/** Unit length */
|
||||
Vector3 m_direction;
|
||||
|
||||
/** 1.0 / direction */
|
||||
Vector3 m_invDirection;
|
||||
|
||||
|
||||
// The following are for the "ray slope" optimization from
|
||||
// "Fast Ray / Axis-Aligned Bounding Box Overlap Tests using Ray Slopes"
|
||||
// by Martin Eisemann, Thorsten Grosch, Stefan Müller and Marcus Magnor
|
||||
// Computer Graphics Lab, TU Braunschweig, Germany and
|
||||
// University of Koblenz-Landau, Germany*/
|
||||
enum Classification {MMM, MMP, MPM, MPP, PMM, PMP, PPM, PPP, POO, MOO, OPO, OMO, OOP, OOM, OMM, OMP, OPM, OPP, MOM, MOP, POM, POP, MMO, MPO, PMO, PPO}; Classification classification;
|
||||
// ray slope
|
||||
float ibyj, jbyi, kbyj, jbyk, ibyk, kbyi;
|
||||
// Precomputed components
|
||||
float c_xy, c_xz, c_yx, c_yz, c_zx, c_zy;
|
||||
|
||||
public:
|
||||
Vector3 origin;
|
||||
|
||||
void set(const Vector3& origin, const Vector3& direction);
|
||||
|
||||
inline const Vector3& origin() const {
|
||||
return m_origin;
|
||||
}
|
||||
|
||||
/** Unit direction vector. */
|
||||
inline const Vector3& direction() const {
|
||||
return m_direction;
|
||||
}
|
||||
|
||||
/** Component-wise inverse of direction vector. May have inf() components */
|
||||
inline const Vector3& invDirection() const {
|
||||
return m_invDirection;
|
||||
}
|
||||
|
||||
inline Ray() {
|
||||
set(Vector3::zero(), Vector3::unitX());
|
||||
}
|
||||
|
||||
inline Ray(const Vector3& origin, const Vector3& direction) {
|
||||
set(origin, direction);
|
||||
}
|
||||
|
||||
Ray(class BinaryInput& b);
|
||||
|
||||
void serialize(class BinaryOutput& b) const;
|
||||
void deserialize(class BinaryInput& b);
|
||||
|
||||
/**
|
||||
Not unit length
|
||||
*/
|
||||
Vector3 direction;
|
||||
|
||||
Ray() : origin(Vector3::zero()), direction(Vector3::zero()) {}
|
||||
|
||||
virtual ~Ray() {}
|
||||
|
||||
/**
|
||||
Creates a Ray from a origin and a (nonzero) direction.
|
||||
Creates a Ray from a origin and a (nonzero) unit direction.
|
||||
*/
|
||||
static Ray fromOriginAndDirection(const Vector3& point, const Vector3& direction) {
|
||||
return Ray(point, direction);
|
||||
}
|
||||
|
||||
Ray unit() const {
|
||||
return Ray(origin, direction.unit());
|
||||
}
|
||||
/** Advances the origin along the direction by @a distance */
|
||||
inline Ray bump(float distance) const {
|
||||
return Ray(m_origin + m_direction * distance, m_direction);
|
||||
}
|
||||
|
||||
/** Advances the origin along the @a bumpDirection by @a distance and returns the new ray*/
|
||||
inline Ray bump(float distance, const Vector3& bumpDirection) const {
|
||||
return Ray(m_origin + bumpDirection * distance, m_direction);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the closest point on the Ray to point.
|
||||
*/
|
||||
Vector3 closestPoint(const Vector3& point) const {
|
||||
float t = direction.dot(point - this->origin);
|
||||
float t = m_direction.dot(point - m_origin);
|
||||
if (t < 0) {
|
||||
return this->origin;
|
||||
return m_origin;
|
||||
} else {
|
||||
return this->origin + direction * t;
|
||||
return m_origin + m_direction * t;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -80,7 +122,7 @@ public:
|
|||
Vector3 intersection(const class Plane& plane) const;
|
||||
|
||||
/**
|
||||
Returns the distance until intersection with the (solid) sphere.
|
||||
Returns the distance until intersection with the sphere or the (solid) ball bounded by the sphere.
|
||||
Will be 0 if inside the sphere, inf if there is no intersection.
|
||||
|
||||
The ray direction is <B>not</B> normalized. If the ray direction
|
||||
|
|
@ -90,8 +132,10 @@ public:
|
|||
|
||||
See also the G3D::CollisionDetection "movingPoint" methods,
|
||||
which give more information about the intersection.
|
||||
|
||||
\param solid If true, rays inside the sphere immediately intersect (good for collision detection). If false, they hit the opposite side of the sphere (good for ray tracing).
|
||||
*/
|
||||
float intersectionTime(const class Sphere& sphere) const;
|
||||
float intersectionTime(const class Sphere& sphere, bool solid = false) const;
|
||||
|
||||
float intersectionTime(const class Plane& plane) const;
|
||||
|
||||
|
|
@ -147,7 +191,7 @@ public:
|
|||
inline float intersectionTime(const Triangle& triangle) const {
|
||||
return intersectionTime(
|
||||
triangle.vertex(0), triangle.vertex(1), triangle.vertex(2),
|
||||
triangle.edge01, triangle.edge02);
|
||||
triangle.edge01(), triangle.edge02());
|
||||
}
|
||||
|
||||
inline float intersectionTime(
|
||||
|
|
@ -156,7 +200,7 @@ public:
|
|||
double& w1,
|
||||
double& w2) const {
|
||||
return intersectionTime(triangle.vertex(0), triangle.vertex(1), triangle.vertex(2),
|
||||
triangle.edge01, triangle.edge02, w0, w1, w2);
|
||||
triangle.edge01(), triangle.edge02(), w0, w1, w2);
|
||||
}
|
||||
|
||||
/** Refracts about the normal
|
||||
|
|
@ -207,33 +251,33 @@ inline float Ray::intersectionTime(
|
|||
float tvec[3], pvec[3], qvec[3];
|
||||
|
||||
// begin calculating determinant - also used to calculate U parameter
|
||||
CROSS(pvec, direction, edge2);
|
||||
CROSS(pvec, m_direction, edge2);
|
||||
|
||||
// if determinant is near zero, ray lies in plane of triangle
|
||||
const float det = DOT(edge1, pvec);
|
||||
|
||||
if (det < EPSILON) {
|
||||
return (float)inf();
|
||||
return finf();
|
||||
}
|
||||
|
||||
// calculate distance from vert0 to ray origin
|
||||
SUB(tvec, origin, vert0);
|
||||
SUB(tvec, m_origin, vert0);
|
||||
|
||||
// calculate U parameter and test bounds
|
||||
u = DOT(tvec, pvec);
|
||||
if ((u < 0.0f) || (u > det)) {
|
||||
// Hit the plane outside the triangle
|
||||
return (float)inf();
|
||||
return finf();
|
||||
}
|
||||
|
||||
// prepare to test V parameter
|
||||
CROSS(qvec, tvec, edge1);
|
||||
|
||||
// calculate V parameter and test bounds
|
||||
v = DOT(direction, qvec);
|
||||
v = DOT(m_direction, qvec);
|
||||
if ((v < 0.0f) || (u + v > det)) {
|
||||
// Hit the plane outside the triangle
|
||||
return (float)inf();
|
||||
return finf();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -245,7 +289,7 @@ inline float Ray::intersectionTime(
|
|||
return t / det;
|
||||
} else {
|
||||
// We had to travel backwards in time to intersect
|
||||
return (float)inf();
|
||||
return finf();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -269,33 +313,33 @@ inline float Ray::intersectionTime(
|
|||
float tvec[3], pvec[3], qvec[3];
|
||||
|
||||
// begin calculating determinant - also used to calculate U parameter
|
||||
CROSS(pvec, direction, edge2);
|
||||
CROSS(pvec, m_direction, edge2);
|
||||
|
||||
// if determinant is near zero, ray lies in plane of triangle
|
||||
const float det = DOT(edge1, pvec);
|
||||
|
||||
if (det < EPSILON) {
|
||||
return (float)inf();
|
||||
return finf();
|
||||
}
|
||||
|
||||
// calculate distance from vert0 to ray origin
|
||||
SUB(tvec, origin, vert0);
|
||||
SUB(tvec, m_origin, vert0);
|
||||
|
||||
// calculate U parameter and test bounds
|
||||
u = DOT(tvec, pvec);
|
||||
if ((u < 0.0f) || (u > det)) {
|
||||
// Hit the plane outside the triangle
|
||||
return (float)inf();
|
||||
return finf();
|
||||
}
|
||||
|
||||
// prepare to test V parameter
|
||||
CROSS(qvec, tvec, edge1);
|
||||
|
||||
// calculate V parameter and test bounds
|
||||
v = DOT(direction, qvec);
|
||||
v = DOT(m_direction, qvec);
|
||||
if ((v < 0.0f) || (u + v > det)) {
|
||||
// Hit the plane outside the triangle
|
||||
return (float)inf();
|
||||
return finf();
|
||||
}
|
||||
|
||||
float t = DOT(edge2, qvec);
|
||||
|
|
@ -313,7 +357,7 @@ inline float Ray::intersectionTime(
|
|||
return t;
|
||||
} else {
|
||||
// We had to travel backwards in time to intersect
|
||||
return (float)inf();
|
||||
return finf();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
417
dep/include/g3dlite/G3D/Rect2D.h
Normal file
417
dep/include/g3dlite/G3D/Rect2D.h
Normal file
|
|
@ -0,0 +1,417 @@
|
|||
/**
|
||||
@file Rect2D.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2003-11-13
|
||||
@created 2009-11-16
|
||||
|
||||
Copyright 2000-2009, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_Rect2D_h
|
||||
#define G3D_Rect2D_h
|
||||
|
||||
// Linux defines this as a macro
|
||||
#ifdef border
|
||||
#undef border
|
||||
#endif
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Array.h"
|
||||
#include "G3D/Vector2.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Turn off "conditional expression is constant" warning; MSVC generates this
|
||||
// for debug assertions in inlined methods.
|
||||
# pragma warning (disable : 4127)
|
||||
#endif
|
||||
|
||||
|
||||
namespace G3D {
|
||||
|
||||
class Any;
|
||||
|
||||
/**
|
||||
If you are using this class for pixel rectangles, keep in mind that the last
|
||||
pixel you can draw to is at x0() + width() - 1.
|
||||
*/
|
||||
class Rect2D {
|
||||
private:
|
||||
Vector2 min, max;
|
||||
|
||||
/**
|
||||
Returns true if the whole polygon is clipped.
|
||||
@param p Value of the point
|
||||
@param axis Index [0 or 1] of the axis to clip along?
|
||||
@param clipGreater Are we clipping greater than or less than the line?
|
||||
@param inPoly Polygon being clipped
|
||||
@param outPoly The clipped polygon
|
||||
*/
|
||||
template<class T>
|
||||
static bool clipSide2D(
|
||||
const float p, bool clipGreater, int axis,
|
||||
const Array<T>& inPoly, Array<T>& outPoly) {
|
||||
|
||||
outPoly.clear();
|
||||
int i0 = -1;
|
||||
|
||||
Vector2 pt1;
|
||||
bool c1 = true;
|
||||
|
||||
float negate = clipGreater ? -1 : 1;
|
||||
|
||||
// Find a point that is not clipped
|
||||
for (i0 = 0; (i0 < inPoly.length()) && c1; ++i0) {
|
||||
pt1 = inPoly[i0];
|
||||
c1 = (negate * pt1[axis]) < (negate * p);
|
||||
}
|
||||
|
||||
// We incremented i0 one time to many
|
||||
--i0;
|
||||
|
||||
if (c1) {
|
||||
// We could not find an unclipped point
|
||||
return true;
|
||||
}
|
||||
|
||||
outPoly.append(pt1);
|
||||
|
||||
// for each point in inPoly,
|
||||
// if the point is outside the side and the previous one was also outside, continue
|
||||
// if the point is outside the side and the previous one was inside, cut the line
|
||||
// if the point is inside the side and the previous one was also inside, append the points
|
||||
// if the point is inside the side and the previous one was outside, cut the line
|
||||
for (int i = 1; i <= inPoly.length(); ++i) {
|
||||
T pt2 = inPoly[(i + i0) % inPoly.length()];
|
||||
bool c2 = (negate * pt2[axis]) < (negate * p);
|
||||
|
||||
if (c1 ^ c2) {
|
||||
|
||||
if (!c1 && c2 && (i > 1)) {
|
||||
// Unclipped to clipped trasition and not the first iteration
|
||||
outPoly.append(pt1);
|
||||
}
|
||||
|
||||
// only one point is clipped, find where the line crosses the clipping plane
|
||||
|
||||
|
||||
float alpha;
|
||||
if (pt2[axis] == pt1[axis]) {
|
||||
alpha = 0;
|
||||
} else {
|
||||
alpha = (p - pt1[axis]) / (pt2[axis] - pt1[axis]);
|
||||
}
|
||||
outPoly.append(pt1.lerp(pt2, alpha));
|
||||
} else if (! (c1 || c2) && (i != 1)) {
|
||||
// neither point is clipped (don't do this the first time
|
||||
// because we appended the first pt before the loop)
|
||||
outPoly.append(pt1);
|
||||
}
|
||||
|
||||
pt1 = pt2;
|
||||
c1 = c2;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/** \param any Must either Rect2D::xywh(#, #, #, #) or Rect2D::xyxy(#, #, #, #)*/
|
||||
Rect2D(const Any& any);
|
||||
|
||||
/** Converts the Rect2D to an Any. */
|
||||
operator Any() const;
|
||||
|
||||
Rect2D() : min(0, 0), max(0, 0) {}
|
||||
|
||||
/** Creates a rectangle at 0,0 with the given width and height*/
|
||||
Rect2D(const Vector2& wh) : min(0, 0), max(wh.x, wh.y) {}
|
||||
|
||||
/** Computes a rectangle that contains both @a a and @a b.
|
||||
Note that even if @a or @b has zero area, its origin will be included.*/
|
||||
Rect2D(const Rect2D& a, const Rect2D& b) {
|
||||
min = a.min.min(b.min);
|
||||
max = a.max.max(b.max);
|
||||
}
|
||||
|
||||
/** @brief Uniformly random point on the interior */
|
||||
Vector2 randomPoint() const {
|
||||
return Vector2(uniformRandom(0, max.x - min.x) + min.x,
|
||||
uniformRandom(0, max.y - min.y) + min.y);
|
||||
}
|
||||
|
||||
float width() const {
|
||||
return max.x - min.x;
|
||||
}
|
||||
|
||||
float height() const {
|
||||
return max.y - min.y;
|
||||
}
|
||||
|
||||
float x0() const {
|
||||
return min.x;
|
||||
}
|
||||
|
||||
float x1() const {
|
||||
return max.x;
|
||||
}
|
||||
|
||||
float y0() const {
|
||||
return min.y;
|
||||
}
|
||||
|
||||
float y1() const {
|
||||
return max.y;
|
||||
}
|
||||
|
||||
/** Min, min corner */
|
||||
Vector2 x0y0() const {
|
||||
return min;
|
||||
}
|
||||
|
||||
Vector2 x1y0() const {
|
||||
return Vector2(max.x, min.y);
|
||||
}
|
||||
|
||||
Vector2 x0y1() const {
|
||||
return Vector2(min.x, max.y);
|
||||
}
|
||||
|
||||
/** Max,max corner */
|
||||
Vector2 x1y1() const {
|
||||
return max;
|
||||
}
|
||||
|
||||
/** Width and height */
|
||||
Vector2 wh() const {
|
||||
return max - min;
|
||||
}
|
||||
|
||||
Vector2 center() const {
|
||||
return (max + min) * 0.5;
|
||||
}
|
||||
|
||||
float area() const {
|
||||
return width() * height();
|
||||
}
|
||||
|
||||
bool isFinite() const {
|
||||
return (min.isFinite() && max.isFinite());
|
||||
}
|
||||
|
||||
Rect2D lerp(const Rect2D& other, float alpha) const {
|
||||
Rect2D out;
|
||||
|
||||
out.min = min.lerp(other.min, alpha);
|
||||
out.max = max.lerp(other.max, alpha);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
static Rect2D xyxy(float x0, float y0, float x1, float y1) {
|
||||
Rect2D r;
|
||||
|
||||
r.min.x = G3D::min(x0, x1);
|
||||
r.min.y = G3D::min(y0, y1);
|
||||
r.max.x = G3D::max(x0, x1);
|
||||
r.max.y = G3D::max(y0, y1);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static Rect2D xyxy(const Vector2& v0, const Vector2& v1) {
|
||||
Rect2D r;
|
||||
|
||||
r.min = v0.min(v1);
|
||||
r.max = v0.max(v1);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static Rect2D xywh(float x, float y, float w, float h) {
|
||||
return xyxy(x, y, x + w, y + h);
|
||||
}
|
||||
|
||||
static Rect2D xywh(const Vector2& v, const Vector2& w) {
|
||||
return xyxy(v.x, v.y, v.x + w.x, v.y + w.y);
|
||||
}
|
||||
|
||||
/** Constructs a Rect2D with infinite boundaries.
|
||||
Use isFinite() to test either min or max.
|
||||
*/
|
||||
static Rect2D inf() {
|
||||
return xyxy(Vector2::inf(), Vector2::inf());
|
||||
}
|
||||
|
||||
bool contains(const Vector2& v) const {
|
||||
return (v.x >= min.x) && (v.y >= min.y) && (v.x <= max.x) && (v.y <= max.y);
|
||||
}
|
||||
|
||||
bool contains(const Rect2D& r) const {
|
||||
return (min.x <= r.min.x) && (min.y <= r.min.y) &&
|
||||
(max.x >= r.max.x) && (max.y >= r.max.y);
|
||||
}
|
||||
|
||||
/** True if there is non-zero area to the intersection between @a this and @a r.
|
||||
Note that two rectangles that are adjacent do not intersect because there is
|
||||
zero area to the overlap, even though one of them "contains" the corners of the other.*/
|
||||
bool intersects(const Rect2D& r) const {
|
||||
return (min.x < r.max.x) && (min.y < r.max.y) &&
|
||||
(max.x > r.min.x) && (max.y > r.min.y);
|
||||
}
|
||||
|
||||
/** Like intersection, but counts the adjacent case as touching. */
|
||||
bool intersectsOrTouches(const Rect2D& r) const {
|
||||
return (min.x <= r.max.x) && (min.y <= r.max.y) &&
|
||||
(max.x >= r.min.x) && (max.y >= r.min.y);
|
||||
}
|
||||
|
||||
Rect2D operator*(float s) const {
|
||||
return xyxy(min.x * s, min.y * s, max.x * s, max.y * s);
|
||||
}
|
||||
|
||||
Rect2D operator/(float s) const {
|
||||
return xyxy(min / s, max / s);
|
||||
}
|
||||
|
||||
Rect2D operator/(const Vector2& s) const {
|
||||
return xyxy(min / s, max / s);
|
||||
}
|
||||
|
||||
Rect2D operator+(const Vector2& v) const {
|
||||
return xyxy(min + v, max + v);
|
||||
}
|
||||
|
||||
Rect2D operator-(const Vector2& v) const {
|
||||
return xyxy(min - v, max - v);
|
||||
}
|
||||
|
||||
bool operator==(const Rect2D& other) const {
|
||||
return (min == other.min) && (max == other.max);
|
||||
}
|
||||
|
||||
bool operator!=(const Rect2D& other) const {
|
||||
return (min != other.min) || (max != other.max);
|
||||
}
|
||||
|
||||
/** Returns the corners in the order: (min,min), (max,min), (max,max), (min,max). */
|
||||
Vector2 corner(int i) const {
|
||||
debugAssert(i >= 0 && i < 4);
|
||||
switch (i & 3) {
|
||||
case 0:
|
||||
return Vector2(min.x, min.y);
|
||||
case 1:
|
||||
return Vector2(max.x, min.y);
|
||||
case 2:
|
||||
return Vector2(max.x, max.y);
|
||||
case 3:
|
||||
return Vector2(min.x, max.y);
|
||||
default:
|
||||
// Should never get here
|
||||
return Vector2(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** @deprecated
|
||||
@sa expand() */
|
||||
Rect2D border(float delta) const {
|
||||
return Rect2D::xywh(x0() + delta,
|
||||
y0() + delta,
|
||||
width() - 2.0f * delta,
|
||||
height() - 2.0f * delta);
|
||||
}
|
||||
|
||||
/** Returns a new Rect2D that is bigger/smaller by the specified amount
|
||||
(negative is shrink.) */
|
||||
Rect2D expand(float delta) const {
|
||||
float newX = x0() - delta;
|
||||
float newY = y0() - delta;
|
||||
float newW = width() + 2.0f * delta;
|
||||
float newH = height() + 2.0f * delta;
|
||||
|
||||
if (newW < 0.0f) {
|
||||
newX = (x0() + width()) / 2.0f;
|
||||
newW = 0.0f;
|
||||
}
|
||||
|
||||
if (newH < 0.0f) {
|
||||
newY = (y0() + height()) / 2.0f;
|
||||
newH = 0.0f;
|
||||
}
|
||||
return Rect2D::xywh(newX, newY, newW, newH);
|
||||
}
|
||||
|
||||
/**
|
||||
Clips so that the rightmost point of the outPoly is at rect.x1 (e.g. a 800x600 window produces
|
||||
rightmost point 799, not 800). The results are suitable for pixel rendering if iRounded.
|
||||
Templated so that it will work for Vector2,3,4 (the z and w components are interpolated linearly).
|
||||
The template parameter must define T.lerp and contain x and y components.
|
||||
|
||||
If the entire polygon is clipped by a single side, the result will be empty.
|
||||
The result might also have zero area but not be empty.
|
||||
*/
|
||||
template<class T>
|
||||
void clip(const Array<T>& inPoly, Array<T>& outPoly) const {
|
||||
|
||||
const bool greaterThan = true;
|
||||
const bool lessThan = false;
|
||||
const int X = 0;
|
||||
const int Y = 1;
|
||||
|
||||
Array<T> temp;
|
||||
|
||||
bool entirelyClipped =
|
||||
clipSide2D(x0(), lessThan, X, inPoly, temp) ||
|
||||
clipSide2D(x1(), greaterThan, X, temp, outPoly) ||
|
||||
clipSide2D(y0(), lessThan, Y, outPoly, temp) ||
|
||||
clipSide2D(y1(), greaterThan, Y, temp, outPoly);
|
||||
|
||||
if (entirelyClipped) {
|
||||
outPoly.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Returns the largest, centered Rect2D that can fit inside this
|
||||
while maintaining the aspect ratio of x:y. Convenient for
|
||||
displaying images in odd-shaped windows.
|
||||
*/
|
||||
Rect2D largestCenteredSubRect(float ww, float hh) const {
|
||||
float textureAspect = hh / ww;
|
||||
float viewAspect = height() / width();
|
||||
|
||||
if (viewAspect > textureAspect) {
|
||||
// The view is too tall
|
||||
float h = width() * textureAspect;
|
||||
float y = (height() - h) / 2;
|
||||
return Rect2D::xywh(0, y, width(), h) + corner(0);
|
||||
} else {
|
||||
// The view is too wide
|
||||
float w = height() / textureAspect;
|
||||
float x = (width() - w) / 2;
|
||||
return Rect2D::xywh(x, 0, w, height()) + corner(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the overlap region between the two rectangles. This may have zero area
|
||||
if they do not intersect. See the two-Rect2D constructor for a way to compute
|
||||
a union-like rectangle.
|
||||
*/
|
||||
Rect2D intersect(const Rect2D& other) const {
|
||||
if (intersects(other)) {
|
||||
return Rect2D::xyxy(min.max(other.min), max.min(other.max));
|
||||
}else{
|
||||
return Rect2D::xywh(0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
typedef Rect2D AABox2D;
|
||||
}
|
||||
|
||||
#endif
|
||||
570
dep/include/g3dlite/G3D/ReferenceCount.h
Normal file
570
dep/include/g3dlite/G3D/ReferenceCount.h
Normal file
|
|
@ -0,0 +1,570 @@
|
|||
/**
|
||||
@file ReferenceCount.h
|
||||
|
||||
Reference Counting Garbage Collector for C++
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
@cite Adapted and extended from Justin Miller's "RGC" class that appeared in BYTE magazine.
|
||||
@cite See also http://www.jelovic.com/articles/cpp_without_memory_errors_slides.htm
|
||||
|
||||
@created 2001-10-23
|
||||
@edited 2009-04-25
|
||||
*/
|
||||
#ifndef G3D_ReferenceCount_h
|
||||
#define G3D_ReferenceCount_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/debug.h"
|
||||
#include "G3D/AtomicInt32.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Turn off "conditional expression is constant" warning; MSVC generates this
|
||||
// for debug assertions in inlined methods.
|
||||
# pragma warning (disable : 4127)
|
||||
#endif
|
||||
|
||||
/** Base class for WeakReferenceCountedPointer */
|
||||
class _WeakPtr {
|
||||
public:
|
||||
inline virtual ~_WeakPtr() {}
|
||||
|
||||
protected:
|
||||
friend class ReferenceCountedObject;
|
||||
|
||||
/** Called by ReferenceCountedObject to tell a weak pointer that its underlying object was collected. */
|
||||
virtual void objectCollected() = 0;
|
||||
};
|
||||
|
||||
/** Used internally by ReferenceCountedObject */
|
||||
class _WeakPtrLinkedList {
|
||||
public:
|
||||
_WeakPtr* weakPtr;
|
||||
_WeakPtrLinkedList* next;
|
||||
|
||||
inline _WeakPtrLinkedList() : weakPtr(NULL), next(NULL) {}
|
||||
|
||||
/** Inserts this node into the head of the list that previously had n as its head. */
|
||||
inline _WeakPtrLinkedList(_WeakPtr* p, _WeakPtrLinkedList* n) : weakPtr(p), next(n) {}
|
||||
};
|
||||
|
||||
/**
|
||||
Objects that are reference counted inherit from this. Subclasses
|
||||
<B>must</B> have a public destructor (the default destructor is fine)
|
||||
and <B>publicly</B> inherit ReferenceCountedObject.
|
||||
|
||||
Multiple inheritance from a reference counted object is dangerous-- use
|
||||
at your own risk.
|
||||
|
||||
ReferenceCountedPointer and ReferenceCountedObject are threadsafe.
|
||||
You can create and drop references on multiple threads without
|
||||
violating integrity. WeakReferenceCountedPointer is <i>not</i>
|
||||
threadsafe. Introducing a weak pointer destroys all thread safety,
|
||||
even for strong pointers to the same object (this is inherent in the
|
||||
design of the class; we cannot fix it without slowing down the
|
||||
performance of reference counted objects.)
|
||||
|
||||
<B>Usage Example</B>
|
||||
|
||||
<PRE>
|
||||
|
||||
class Foo : public G3D::ReferenceCountedObject {
|
||||
public:
|
||||
int x;
|
||||
};
|
||||
|
||||
class Bar : public Foo {};
|
||||
|
||||
typedef G3D::ReferenceCountedPointer<Foo> FooRef;
|
||||
typedef G3D::WeakReferenceCountedPointer<Foo> WeakFooRef;
|
||||
typedef G3D::ReferenceCountedPointer<Bar> BarRef;
|
||||
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
WeakFooRef x;
|
||||
|
||||
{
|
||||
FooRef a = new Foo();
|
||||
|
||||
// Reference count == 1
|
||||
|
||||
x = a;
|
||||
// Weak references do not increase count
|
||||
|
||||
{
|
||||
FooRef b = a;
|
||||
// Reference count == 2
|
||||
}
|
||||
|
||||
// Reference count == 1
|
||||
}
|
||||
// No more strong references; object automatically deleted.
|
||||
// x is set to NULL automatically.
|
||||
|
||||
// Example of using dynamic cast on reference counted objects
|
||||
BarRef b = new Bar();
|
||||
|
||||
// No cast needed to go down the heirarchy.
|
||||
FooRef f = b;
|
||||
|
||||
// We can't cast the reference object because it is a class.
|
||||
// Instead we must extract the pointer and cast that:
|
||||
b = dynamic_cast<Bar*>(&*f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
</PRE>
|
||||
*/
|
||||
class ReferenceCountedObject {
|
||||
public:
|
||||
|
||||
/**
|
||||
The long name is to keep this from accidentally conflicting with
|
||||
a subclass's variable name. Do not use or explicitly manipulate
|
||||
this value--its type may change in the future and is not part
|
||||
of the supported API.
|
||||
*/
|
||||
AtomicInt32 ReferenceCountedObject_refCount;
|
||||
|
||||
/**
|
||||
Linked list of all weak pointers that reference this (some may be
|
||||
on the stack!). Do not use or explicitly manipulate this value.
|
||||
*/
|
||||
_WeakPtrLinkedList* ReferenceCountedObject_weakPointer;
|
||||
|
||||
protected:
|
||||
|
||||
ReferenceCountedObject();
|
||||
|
||||
public:
|
||||
|
||||
/** Automatically called immediately before the object is deleted.
|
||||
This is not called from the destructor because it needs to be invoked
|
||||
before the subclass destructor.
|
||||
*/
|
||||
void ReferenceCountedObject_zeroWeakPointers();
|
||||
|
||||
virtual ~ReferenceCountedObject();
|
||||
|
||||
|
||||
/**
|
||||
Note: copies will initially start out with 0
|
||||
references and 0 weak references like any other object.
|
||||
*/
|
||||
ReferenceCountedObject(const ReferenceCountedObject& notUsed);
|
||||
|
||||
ReferenceCountedObject& operator=(const ReferenceCountedObject& other);
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Use ReferenceCountedPointer<T> in place of T* in your program.
|
||||
T must subclass ReferenceCountedObject.
|
||||
@deprecated To be replaced by boost::shared_ptr in 7.0
|
||||
*/
|
||||
template <class T>
|
||||
class ReferenceCountedPointer {
|
||||
private:
|
||||
|
||||
T* m_pointer;
|
||||
|
||||
public:
|
||||
typedef T element_type;
|
||||
|
||||
inline T* pointer() const {
|
||||
return m_pointer;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/** Nulls out the pointer and drops a reference. If the reference
|
||||
count hits zero. */
|
||||
void zeroPointer() {
|
||||
if (m_pointer != NULL) {
|
||||
|
||||
ReferenceCountedObject* pointer = ((ReferenceCountedObject*)m_pointer);
|
||||
debugAssert(G3D::isValidHeapPointer(m_pointer));
|
||||
debugAssertM(pointer->ReferenceCountedObject_refCount.value() > 0,
|
||||
"Dangling reference detected.");
|
||||
|
||||
// Only delete if this instance caused the count to hit
|
||||
// exactly zero. If there is a race condition, the value
|
||||
// may be zero after decrement returns, but only one of
|
||||
// the instances will get a zero return value.
|
||||
if (pointer->ReferenceCountedObject_refCount.decrement() == 0) {
|
||||
// We held the last reference, so delete the object.
|
||||
// This test is threadsafe because there is no way for
|
||||
// the reference count to increase after the last
|
||||
// reference was dropped (assuming the application does
|
||||
// not voilate the class abstraction).
|
||||
//debugPrintf(" delete 0x%x\n", m_pointer);
|
||||
|
||||
// We must zero the weak pointers *before* deletion in case there
|
||||
// are cycles of weak references.
|
||||
// Note that since there are no strong references at this point,
|
||||
// it is perfectly fair to zero the weak pointers anyway.
|
||||
pointer->ReferenceCountedObject_zeroWeakPointers();
|
||||
delete pointer;
|
||||
}
|
||||
|
||||
m_pointer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/** Non-atomic (except for the referencec increment). Can only be
|
||||
called in contexts like the copy constructor or initial
|
||||
constructor where it is known that the reference count will
|
||||
not hit zero on some other thread. */
|
||||
void setPointer(T* x) {
|
||||
if (x != m_pointer) {
|
||||
zeroPointer();
|
||||
|
||||
if (x != NULL) {
|
||||
debugAssert(G3D::isValidHeapPointer(x));
|
||||
|
||||
m_pointer = x;
|
||||
|
||||
// Note that the ref count can be zero if this is the
|
||||
// first pointer to it
|
||||
ReferenceCountedObject* pointer = (ReferenceCountedObject*)m_pointer;
|
||||
debugAssertM(pointer->ReferenceCountedObject_refCount.value() >= 0,
|
||||
"Negative reference count detected.");
|
||||
pointer->ReferenceCountedObject_refCount.increment();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
inline ReferenceCountedPointer() : m_pointer(NULL) {}
|
||||
|
||||
/**
|
||||
Allow silent cast <i>to</i> the base class.
|
||||
|
||||
<pre>
|
||||
SubRef s = new Sub();
|
||||
BaseRef b = s;
|
||||
</pre>
|
||||
|
||||
i.e., compile-time subtyping rule
|
||||
RCP<<I>T</I>> <: RCP<<I>S</I>> if <I>T</I> <: <I>S</I>
|
||||
*/
|
||||
template <class S>
|
||||
inline ReferenceCountedPointer(const ReferenceCountedPointer<S>& p) :
|
||||
m_pointer(NULL) {
|
||||
setPointer(p.pointer());
|
||||
}
|
||||
|
||||
# if (! defined(MSC_VER) || (MSC_VER >= 1300))
|
||||
/**
|
||||
Explicit cast to a subclass. Acts like dynamic cast; the result will be NULL if
|
||||
the cast cannot succeed. Not supported on VC6.
|
||||
<pre>
|
||||
SubRef s = new Sub();
|
||||
BaseRef b = s;
|
||||
s = b.downcast<Sub>(); // Note that the template argument is the object type, not the pointer type.
|
||||
</pre>
|
||||
*/
|
||||
template <class S>
|
||||
ReferenceCountedPointer<S> downcast() {
|
||||
return ReferenceCountedPointer<S>(dynamic_cast<S*>(m_pointer));
|
||||
}
|
||||
|
||||
template <class S>
|
||||
const ReferenceCountedPointer<S> downcast() const {
|
||||
return ReferenceCountedPointer<S>(dynamic_cast<const S*>(m_pointer));
|
||||
}
|
||||
# endif
|
||||
|
||||
// We need an explicit version of the copy constructor as well or
|
||||
// the default copy constructor will be used.
|
||||
inline ReferenceCountedPointer(const ReferenceCountedPointer<T>& p) : m_pointer(NULL) {
|
||||
setPointer(p.m_pointer);
|
||||
}
|
||||
|
||||
/** Allows construction from a raw pointer. That object will thereafter be
|
||||
reference counted -- do not call delete on it.
|
||||
|
||||
Use of const allows downcast on const references */
|
||||
inline ReferenceCountedPointer(const T* p) : m_pointer(NULL) {
|
||||
// only const constructor is defined to remove ambiguity using NULL
|
||||
setPointer(const_cast<T*>(p));
|
||||
}
|
||||
|
||||
|
||||
inline ~ReferenceCountedPointer() {
|
||||
zeroPointer();
|
||||
}
|
||||
|
||||
inline size_t hashCode() const {
|
||||
return reinterpret_cast<size_t>(m_pointer);;
|
||||
}
|
||||
|
||||
inline const ReferenceCountedPointer<T>& operator=(const ReferenceCountedPointer<T>& p) {
|
||||
setPointer(p.m_pointer);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline ReferenceCountedPointer<T>& operator=(T* p) {
|
||||
setPointer(p);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline bool operator==(const ReferenceCountedPointer<T>& y) const {
|
||||
return (m_pointer == y.m_pointer);
|
||||
}
|
||||
|
||||
inline bool operator!=(const ReferenceCountedPointer<T>& y) const {
|
||||
return (m_pointer != y.m_pointer);
|
||||
}
|
||||
|
||||
bool operator < (const ReferenceCountedPointer<T>& y) const {
|
||||
return (m_pointer < y.m_pointer);
|
||||
}
|
||||
|
||||
bool operator > (const ReferenceCountedPointer<T>& y) const {
|
||||
return (m_pointer > y.m_pointer);
|
||||
}
|
||||
|
||||
bool operator <= (const ReferenceCountedPointer<T>& y) const {
|
||||
return (m_pointer <= y.m_pointer);
|
||||
}
|
||||
|
||||
bool operator >= (const ReferenceCountedPointer<T>& y) const {
|
||||
return (m_pointer >= y.m_pointer);
|
||||
}
|
||||
|
||||
inline T& operator*() const {
|
||||
debugAssertM(m_pointer != NULL, "Dereferenced a NULL ReferenceCountedPointer");
|
||||
return (*m_pointer);
|
||||
}
|
||||
|
||||
inline T* operator->() const {
|
||||
debugAssertM(m_pointer != NULL, "Dereferenced a NULL ReferenceCountedPointer");
|
||||
return m_pointer;
|
||||
}
|
||||
|
||||
inline bool isNull() const {
|
||||
return (m_pointer == NULL);
|
||||
}
|
||||
|
||||
inline bool notNull() const {
|
||||
return (m_pointer != NULL);
|
||||
}
|
||||
|
||||
// TODO: distinguish between last strong and last any pointer
|
||||
/**
|
||||
Returns true if this is the last reference to an object.
|
||||
Useful for flushing memoization caches-- a cache that holds the last
|
||||
reference is unnecessarily keeping an object alive.
|
||||
|
||||
<b>Not threadsafe.</b>
|
||||
|
||||
@deprecated Use WeakReferenceCountedPointer for caches
|
||||
*/
|
||||
inline int isLastReference() const {
|
||||
return (m_pointer->ReferenceCountedObject_refCount.value() == 1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
A weak pointer allows the object it references to be garbage collected.
|
||||
Weak pointers are commonly used in caches, where it is important to hold
|
||||
a pointer to an object without keeping that object alive solely for the
|
||||
cache's benefit (i.e., the object can be collected as soon as all
|
||||
pointers to it <B>outside</B> the cache are gone). They are also convenient
|
||||
for adding back-pointers in tree and list structures.
|
||||
|
||||
Weak pointers may become NULL at any point (when their target is collected).
|
||||
Therefore the only way to reference the target is to convert to a strong
|
||||
pointer and then check that it is not NULL.
|
||||
|
||||
@deprecated To be replaced by boost::weak_ptr in 7.0
|
||||
*/
|
||||
template <class T>
|
||||
class WeakReferenceCountedPointer : public _WeakPtr {
|
||||
private:
|
||||
|
||||
/** NULL if the object has been collected. */
|
||||
T* pointer;
|
||||
|
||||
public:
|
||||
/**
|
||||
Creates a strong pointer, which prevents the object from being
|
||||
garbage collected. The strong pointer may be NULL, which means
|
||||
that the underlying.
|
||||
*/
|
||||
// There is intentionally no way to check if the
|
||||
// WeakReferenceCountedPointer has a null reference without
|
||||
// creating a strong pointer since there is no safe way to use
|
||||
// that information-- the pointer could be collected by a
|
||||
// subsequent statement.
|
||||
ReferenceCountedPointer<T> createStrongPtr() const {
|
||||
// TODO: What if the object's destructor is called while we
|
||||
// are in this method?
|
||||
return ReferenceCountedPointer<T>(pointer);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/** Thread issues: safe because this is only called when another
|
||||
object is guaranteed to keep p alive for the duration of this
|
||||
call. */
|
||||
void setPointer(T* p) {
|
||||
// TODO: must prevent the object from being collected while in
|
||||
// this method
|
||||
|
||||
zeroPointer();
|
||||
pointer = p;
|
||||
|
||||
if (pointer != NULL) {
|
||||
// TODO: threadsafe: must update the list atomically
|
||||
|
||||
// Add myself to the head of my target's list of weak pointers
|
||||
_WeakPtrLinkedList* head =
|
||||
new _WeakPtrLinkedList
|
||||
(this,
|
||||
pointer->ReferenceCountedObject_weakPointer);
|
||||
|
||||
pointer->ReferenceCountedObject_weakPointer = head;
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Removes this from its target's list of weak pointers. Called
|
||||
when the weak pointer goes out of scope.
|
||||
|
||||
Thread issues: depends on the thread safety of createStrongPtr.
|
||||
*/
|
||||
void zeroPointer() {
|
||||
// Grab a strong reference to prevent the object from being collected while we
|
||||
// are traversing its list.
|
||||
ReferenceCountedPointer<T> strong = createStrongPtr();
|
||||
|
||||
// If the following test fails then the object was collected before we
|
||||
// reached it.
|
||||
if (strong.notNull()) {
|
||||
debugAssertM(((ReferenceCountedObject*)pointer)->ReferenceCountedObject_weakPointer != NULL,
|
||||
"Weak pointer exists without a backpointer from the object.");
|
||||
|
||||
// Remove myself from my target's list of weak pointers
|
||||
_WeakPtrLinkedList** node = &((ReferenceCountedObject*)pointer)->ReferenceCountedObject_weakPointer;
|
||||
while ((*node)->weakPtr != this) {
|
||||
node = &((*node)->next);
|
||||
debugAssertM(*node != NULL,
|
||||
"Weak pointer exists without a backpointer from the object (2).");
|
||||
}
|
||||
|
||||
// Node must now point at the node for me. Remove node and
|
||||
// close the linked list behind it.
|
||||
_WeakPtrLinkedList* temp = *node;
|
||||
*node = temp->next;
|
||||
|
||||
// Now delete the node corresponding to me
|
||||
delete temp;
|
||||
}
|
||||
|
||||
pointer = NULL;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
WeakReferenceCountedPointer() : pointer(0) {}
|
||||
|
||||
/**
|
||||
Allow compile time subtyping rule
|
||||
RCP<<I>T</I>> <: RCP<<I>S</I>> if <I>T</I> <: <I>S</I>
|
||||
*/
|
||||
template <class S>
|
||||
inline WeakReferenceCountedPointer(const WeakReferenceCountedPointer<S>& p) : pointer(0) {
|
||||
// Threadsafe: the object cannot be collected while the other pointer exists.
|
||||
setPointer(p.pointer);
|
||||
}
|
||||
|
||||
template <class S>
|
||||
inline WeakReferenceCountedPointer(const ReferenceCountedPointer<S>& p) : pointer(0) {
|
||||
// Threadsafe: the object cannot be collected while the other
|
||||
// pointer exists.
|
||||
setPointer(p.pointer());
|
||||
}
|
||||
|
||||
// Gets called a *lot* when weak pointers are on the stack
|
||||
WeakReferenceCountedPointer(
|
||||
const WeakReferenceCountedPointer<T>& weakPtr) : pointer(0) {
|
||||
setPointer(weakPtr.pointer);
|
||||
}
|
||||
|
||||
WeakReferenceCountedPointer(
|
||||
const ReferenceCountedPointer<T>& strongPtr) : pointer(0) {
|
||||
setPointer(strongPtr.pointer());
|
||||
}
|
||||
|
||||
~WeakReferenceCountedPointer() {
|
||||
zeroPointer();
|
||||
}
|
||||
|
||||
WeakReferenceCountedPointer<T>& operator=(const WeakReferenceCountedPointer<T>& other) {
|
||||
// Threadsafe: the object cannot be collected while the other pointer exists.
|
||||
|
||||
// I now point at other's target
|
||||
setPointer(other.pointer);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
WeakReferenceCountedPointer<T>& operator=(const ReferenceCountedPointer<T>& other) {
|
||||
|
||||
// Threadsafe: the object cannot be collected while the other pointer exists.
|
||||
|
||||
// I now point at other's target
|
||||
setPointer(other.pointer());
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const WeakReferenceCountedPointer<T>& other) const {
|
||||
return pointer == other.pointer;
|
||||
}
|
||||
|
||||
bool operator!=(const WeakReferenceCountedPointer<T>& other) const {
|
||||
return pointer != other.pointer;
|
||||
}
|
||||
|
||||
bool operator < (const WeakReferenceCountedPointer<T>& y) const {
|
||||
return (pointer < y.pointer);
|
||||
}
|
||||
|
||||
bool operator > (const WeakReferenceCountedPointer<T>& y) const {
|
||||
return (pointer > y.pointer);
|
||||
}
|
||||
|
||||
bool operator <= (const WeakReferenceCountedPointer<T>& y) const {
|
||||
return (pointer <= y.pointer);
|
||||
}
|
||||
|
||||
bool operator >= (const ReferenceCountedPointer<T>& y) const {
|
||||
return (pointer >= y.pointer);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/** Invoked by the destructor on ReferenceCountedPointer. */
|
||||
void objectCollected() {
|
||||
debugAssertM(pointer != NULL,
|
||||
"Removed a weak pointer twice.");
|
||||
pointer = NULL;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -25,7 +25,10 @@ namespace G3D {
|
|||
Provides generalized Windows registry querying.
|
||||
|
||||
All key names are one string in the format:
|
||||
"[base key]\[sub-keys]\value"
|
||||
"[base key]\[sub-keys]"
|
||||
|
||||
A value must now be provided for every query.
|
||||
An empty value string will use the (Default) value.
|
||||
|
||||
[base key] can be any of the following:
|
||||
HKEY_CLASSES_ROOT
|
||||
|
|
@ -37,45 +40,53 @@ namespace G3D {
|
|||
HKEY_PERFORMANCE_TEXT
|
||||
HKEY_USERS
|
||||
|
||||
keyExists() should be used to validate a key before reading or writing
|
||||
to ensure that a debug assert or false return is for a different error.
|
||||
valueExists() should be used to validate a key+value before reading or writing
|
||||
to ensure that a debug assert or false return is for a different error during
|
||||
reads and writes.
|
||||
|
||||
All read and write calls will assert when a key will not open for reasons other
|
||||
that it does not exist. All read and write calls will assert when the value cannot
|
||||
be read or written for any reason.
|
||||
*/
|
||||
class RegistryUtil {
|
||||
|
||||
public:
|
||||
/** returns true if the key exists */
|
||||
/** returns true if the key exists and the current user has permission to read */
|
||||
static bool keyExists(const std::string& key);
|
||||
|
||||
/** returns true if the key exists and the current user has permission to read */
|
||||
static bool valueExists(const std::string& key, const std::string& value);
|
||||
|
||||
/** returns false if the key could not be read for any reason. */
|
||||
static bool readInt32(const std::string& key, int32& valueData);
|
||||
static bool readInt32(const std::string& key, const std::string& value, int32& data);
|
||||
|
||||
/**
|
||||
Reads an arbitrary amount of data from a binary registry key.
|
||||
returns false if the key could not be read for any reason.
|
||||
|
||||
@beta
|
||||
@param valueData pointer to the output buffer of sufficient size. Pass NULL as valueData in order to have available data size returned in dataSize.
|
||||
@param dataSize size of the output buffer. When NULL is passed for valueData, contains the size of available data on successful return.
|
||||
@param data pointer to the output buffer of sufficient size. Pass NULL as data in order to have available data size returned in dataSize.
|
||||
@param dataSize size of the output buffer. When NULL is passed for data, contains the size of available data on successful return.
|
||||
*/
|
||||
static bool readBytes(const std::string& key, uint8* valueData, uint32& dataSize);
|
||||
static bool readBytes(const std::string& key, const std::string& value, uint8* data, uint32& dataSize);
|
||||
|
||||
/** returns false if the key could not be read for any reason. */
|
||||
static bool readString(const std::string& key, std::string& valueData);
|
||||
static bool readString(const std::string& key, const std::string& value, std::string& data);
|
||||
|
||||
/** returns false if the key could not be written for any reason. */
|
||||
static bool writeInt32(const std::string& key, int32 valueData);
|
||||
static bool writeInt32(const std::string& key, const std::string& value, int32 data);
|
||||
|
||||
/**
|
||||
Writes an arbitrary amount of data to a binary registry key.
|
||||
returns false if the key could not be written for any reason.
|
||||
|
||||
@param valueData pointer to the input buffer
|
||||
@param data pointer to the input buffer
|
||||
@param dataSize size of the input buffer that should be written
|
||||
*/
|
||||
static bool writeBytes(const std::string& key, const uint8* valueData, uint32 dataSize);
|
||||
static bool writeBytes(const std::string& key, const std::string& value, const uint8* data, uint32 dataSize);
|
||||
|
||||
/** returns false if the key could not be written for any reason. */
|
||||
static bool writeString(const std::string& key, const std::string& valueData);
|
||||
static bool writeString(const std::string& key, const std::string& value, const std::string& data);
|
||||
|
||||
};
|
||||
|
||||
|
|
@ -83,4 +94,4 @@ public:
|
|||
|
||||
#endif // G3D_WIN32
|
||||
|
||||
#endif // G3D_REGISTRYTUIL_H
|
||||
#endif // G3D_REGISTRYTUIL_H
|
||||
|
|
|
|||
186
dep/include/g3dlite/G3D/Set.h
Normal file
186
dep/include/g3dlite/G3D/Set.h
Normal file
|
|
@ -0,0 +1,186 @@
|
|||
/**
|
||||
@file Set.h
|
||||
|
||||
Hash set
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2001-12-09
|
||||
@edited 2009-06-10
|
||||
*/
|
||||
|
||||
#ifndef G3D_Set_h
|
||||
#define G3D_Set_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Table.h"
|
||||
#include "G3D/MemoryManager.h"
|
||||
#include <assert.h>
|
||||
#include <string>
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
An unordered data structure that has at most one of each element.
|
||||
Provides O(1) time insert, remove, and member test (contains).
|
||||
|
||||
Set uses G3D::Table internally, which means that the template type T
|
||||
must define a hashCode and operator== function. See G3D::Table for
|
||||
a discussion of these functions.
|
||||
*/
|
||||
// There is not copy constructor or assignment operator defined because
|
||||
// the default ones are correct for Set.
|
||||
template<class T, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T> >
|
||||
class Set {
|
||||
|
||||
/**
|
||||
If an object is a member, it is contained in
|
||||
this table.
|
||||
*/
|
||||
Table<T, bool, HashFunc, EqualsFunc> memberTable;
|
||||
|
||||
public:
|
||||
|
||||
void clearAndSetMemoryManager(const MemoryManager::Ref& m) {
|
||||
memberTable.clearAndSetMemoryManager(m);
|
||||
}
|
||||
|
||||
virtual ~Set() {}
|
||||
|
||||
int size() const {
|
||||
return (int)memberTable.size();
|
||||
}
|
||||
|
||||
bool contains(const T& member) const {
|
||||
return memberTable.containsKey(member);
|
||||
}
|
||||
|
||||
/**
|
||||
Inserts into the table if not already present.
|
||||
*/
|
||||
void insert(const T& member) {
|
||||
memberTable.set(member, true);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns true if the element was present and removed. Returns false
|
||||
if the element was not present.
|
||||
*/
|
||||
bool remove(const T& member) {
|
||||
return memberTable.remove(member);
|
||||
}
|
||||
|
||||
/** If @a member is present, sets @a removed to the element
|
||||
being removed and returns true. Otherwise returns false
|
||||
and does not write to @a removed. This is useful when building
|
||||
efficient hashed data structures that wrap Set.
|
||||
*/
|
||||
bool getRemove(const T& member, T& removed) {
|
||||
bool ignore;
|
||||
return memberTable.getRemove(member, removed, ignore);
|
||||
}
|
||||
|
||||
/** If a value that is EqualsFunc to @a member is present, returns a pointer to the
|
||||
version stored in the data structure, otherwise returns NULL.
|
||||
*/
|
||||
const T* getPointer(const T& member) const {
|
||||
return memberTable.getKeyPointer(member);
|
||||
}
|
||||
|
||||
Array<T> getMembers() const {
|
||||
return memberTable.getKeys();
|
||||
}
|
||||
|
||||
void getMembers(Array<T>& keyArray) const {
|
||||
memberTable.getKeys(keyArray);
|
||||
}
|
||||
|
||||
void clear() {
|
||||
memberTable.clear();
|
||||
}
|
||||
|
||||
void deleteAll() {
|
||||
getMembers().deleteAll();
|
||||
clear();
|
||||
}
|
||||
|
||||
/**
|
||||
C++ STL style iterator variable. See begin().
|
||||
*/
|
||||
class Iterator {
|
||||
private:
|
||||
friend class Set<T>;
|
||||
|
||||
// Note: this is a Table iterator, we are currently defining
|
||||
// Set iterator
|
||||
typename Table<T, bool>::Iterator it;
|
||||
|
||||
Iterator(const typename Table<T, bool>::Iterator& it) : it(it) {}
|
||||
|
||||
public:
|
||||
inline bool operator!=(const Iterator& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
bool hasMore() const {
|
||||
return it.hasMore();
|
||||
}
|
||||
|
||||
bool operator==(const Iterator& other) const {
|
||||
return it == other.it;
|
||||
}
|
||||
|
||||
/**
|
||||
Pre increment.
|
||||
*/
|
||||
Iterator& operator++() {
|
||||
++it;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
Post increment (slower than preincrement).
|
||||
*/
|
||||
Iterator operator++(int) {
|
||||
Iterator old = *this;
|
||||
++(*this);
|
||||
return old;
|
||||
}
|
||||
|
||||
const T& operator*() const {
|
||||
return it->key;
|
||||
}
|
||||
|
||||
T* operator->() const {
|
||||
return &(it->key);
|
||||
}
|
||||
|
||||
operator T*() const {
|
||||
return &(it->key);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
C++ STL style iterator method. Returns the first member.
|
||||
Use preincrement (++entry) to get to the next element.
|
||||
Do not modify the set while iterating.
|
||||
*/
|
||||
Iterator begin() const {
|
||||
return Iterator(memberTable.begin());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
C++ STL style iterator method. Returns one after the last iterator
|
||||
element.
|
||||
*/
|
||||
const Iterator end() const {
|
||||
return Iterator(memberTable.end());
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
155
dep/include/g3dlite/G3D/SmallArray.h
Normal file
155
dep/include/g3dlite/G3D/SmallArray.h
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
/**
|
||||
@file SmallArray.h
|
||||
|
||||
@created 2009-04-26
|
||||
@edited 2009-04-26
|
||||
|
||||
Copyright 2000-2009, Morgan McGuire, http://graphics.cs.williams.edu
|
||||
All rights reserved.
|
||||
*/
|
||||
#ifndef G3D_SmallArray_h
|
||||
#define G3D_SmallArray_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Array.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/** Embeds \a N elements to reduce allocation time and increase
|
||||
memory coherence when working with arrays of arrays.
|
||||
Offers a limited subset of the functionality of G3D::Array.*/
|
||||
template<class T, int N>
|
||||
class SmallArray {
|
||||
private:
|
||||
int m_size;
|
||||
|
||||
/** First N elements */
|
||||
T m_embedded[N];
|
||||
|
||||
/** Remaining elements */
|
||||
Array<T> m_rest;
|
||||
|
||||
public:
|
||||
|
||||
SmallArray() : m_size(0) {}
|
||||
|
||||
inline int size() const {
|
||||
return m_size;
|
||||
}
|
||||
|
||||
void resize(int n, bool shrinkIfNecessary = true) {
|
||||
m_rest.resize(std::max(0, n - N), shrinkIfNecessary);
|
||||
m_size = n;
|
||||
}
|
||||
|
||||
void clear(bool shrinkIfNecessary = true) {
|
||||
resize(0, shrinkIfNecessary);
|
||||
}
|
||||
|
||||
inline T& operator[](int i) {
|
||||
debugAssert(i < m_size && i >= 0);
|
||||
if (i < N) {
|
||||
return m_embedded[i];
|
||||
} else {
|
||||
return m_rest[i - N];
|
||||
}
|
||||
}
|
||||
|
||||
inline const T& operator[](int i) const {
|
||||
debugAssert(i < m_size && i >= 0);
|
||||
if (i < N) {
|
||||
return m_embedded[i];
|
||||
} else {
|
||||
return m_rest[i - N];
|
||||
}
|
||||
}
|
||||
|
||||
inline void push(const T& v) {
|
||||
++m_size;
|
||||
if (m_size <= N) {
|
||||
m_embedded[m_size - 1] = v;
|
||||
} else {
|
||||
m_rest.append(v);
|
||||
}
|
||||
}
|
||||
|
||||
inline void append(const T& v) {
|
||||
push(v);
|
||||
}
|
||||
|
||||
void fastRemove(int i) {
|
||||
debugAssert(i < m_size && i >= 0);
|
||||
if (i < N) {
|
||||
if (m_size <= N) {
|
||||
// Exclusively embedded
|
||||
m_embedded[i] = m_embedded[m_size - 1];
|
||||
} else {
|
||||
// Move one down from the rest array
|
||||
m_embedded[i] = m_rest.pop();
|
||||
}
|
||||
} else {
|
||||
// Removing from the rest array
|
||||
m_rest.fastRemove(i - N);
|
||||
}
|
||||
--m_size;
|
||||
}
|
||||
|
||||
T pop() {
|
||||
debugAssert(m_size > 0);
|
||||
if (m_size <= N) {
|
||||
// Popping from embedded, don't need a temporary
|
||||
--m_size;
|
||||
return m_embedded[m_size];
|
||||
} else {
|
||||
// Popping from rest
|
||||
--m_size;
|
||||
return m_rest.pop();
|
||||
}
|
||||
}
|
||||
|
||||
inline void popDiscard() {
|
||||
debugAssert(m_size > 0);
|
||||
if (m_size > N) {
|
||||
m_rest.popDiscard();
|
||||
}
|
||||
--m_size;
|
||||
}
|
||||
|
||||
inline T& next() {
|
||||
++m_size;
|
||||
if (m_size <= N) {
|
||||
return m_embedded[m_size - 1];
|
||||
} else {
|
||||
return m_rest.next();
|
||||
}
|
||||
}
|
||||
|
||||
bool contains(const T& value) const {
|
||||
for (int i = std::min(m_size, N) - 1; i >= 0; --i) {
|
||||
if (m_embedded[i] == value) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return m_rest.contains(value);
|
||||
}
|
||||
|
||||
template<int MIN_ELEMENTS, int MIN_BYTES>
|
||||
SmallArray<T, N>& operator=(const Array<T, MIN_ELEMENTS, MIN_BYTES>& src) {
|
||||
resize(src.size());
|
||||
for (int i = 0; i < src.size(); ++i) {
|
||||
(*this)[i] = src[i];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline const T& last() const {
|
||||
return (*this)[size() - 1];
|
||||
}
|
||||
|
||||
inline T& last() {
|
||||
return (*this)[size() - 1];
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
|
|
@ -3,10 +3,10 @@
|
|||
|
||||
Sphere class
|
||||
|
||||
@maintainer Morgan McGuire, matrix@graphics3d.com
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2001-06-02
|
||||
@edited 2004-07-05
|
||||
@edited 2008-10-07
|
||||
*/
|
||||
|
||||
#ifndef G3D_SPHERE_H
|
||||
|
|
@ -36,6 +36,10 @@ public:
|
|||
radius = 0;
|
||||
}
|
||||
|
||||
Sphere(class BinaryInput& b);
|
||||
void serialize(class BinaryOutput& b) const;
|
||||
void deserialize(class BinaryInput& b);
|
||||
|
||||
Sphere(
|
||||
const Vector3& center,
|
||||
float radius) {
|
||||
|
|
@ -60,51 +64,49 @@ public:
|
|||
*/
|
||||
bool contains(const Vector3& point) const;
|
||||
|
||||
/**
|
||||
@deprecated Use culledBy(Array<Plane>&)
|
||||
*/
|
||||
bool culledBy(
|
||||
const class Plane* plane,
|
||||
int numPlanes,
|
||||
int32& cullingPlaneIndex,
|
||||
const uint32 testMask,
|
||||
uint32& childMask) const;
|
||||
bool contains(const Sphere& other) const;
|
||||
|
||||
/**
|
||||
@deprecated Use culledBy(Array<Plane>&)
|
||||
@deprecated Use culledBy(Array<Plane>&)
|
||||
*/
|
||||
bool culledBy(
|
||||
const class Plane* plane,
|
||||
int numPlanes,
|
||||
int32& cullingPlaneIndex = dummy,
|
||||
const uint32 testMask = -1) const;
|
||||
|
||||
/**
|
||||
See AABox::culledBy
|
||||
*/
|
||||
bool culledBy(
|
||||
const Array<Plane>& plane,
|
||||
int32& cullingPlaneIndex,
|
||||
const uint32 testMask,
|
||||
uint32& childMask) const;
|
||||
const class Plane* plane,
|
||||
int numPlanes,
|
||||
int32& cullingPlaneIndex,
|
||||
const uint32 testMask,
|
||||
uint32& childMask) const;
|
||||
|
||||
/**
|
||||
@deprecated Use culledBy(Array<Plane>&)
|
||||
*/
|
||||
bool culledBy(
|
||||
const class Plane* plane,
|
||||
int numPlanes,
|
||||
int32& cullingPlaneIndex = dummy,
|
||||
const uint32 testMask = 0xFFFFFFFF) const;
|
||||
|
||||
/**
|
||||
See AABox::culledBy
|
||||
*/
|
||||
bool culledBy(
|
||||
const Array<Plane>& plane,
|
||||
int32& cullingPlaneIndex,
|
||||
const uint32 testMask,
|
||||
uint32& childMask) const;
|
||||
|
||||
/**
|
||||
Conservative culling test that does not produce a mask for children.
|
||||
*/
|
||||
bool culledBy(
|
||||
const Array<Plane>& plane,
|
||||
int32& cullingPlaneIndex = dummy,
|
||||
const uint32 testMask = -1) const;
|
||||
bool culledBy(
|
||||
const Array<Plane>& plane,
|
||||
int32& cullingPlaneIndex = dummy,
|
||||
const uint32 testMask = 0xFFFFFFFF) const;
|
||||
|
||||
virtual std::string toString() const;
|
||||
|
||||
float volume() const;
|
||||
|
||||
/** @deprecated */
|
||||
float surfaceArea() const;
|
||||
|
||||
inline float area() const {
|
||||
return surfaceArea();
|
||||
}
|
||||
float area() const;
|
||||
|
||||
/**
|
||||
Uniformly distributed on the surface.
|
||||
|
|
@ -117,12 +119,30 @@ public:
|
|||
Vector3 randomInteriorPoint() const;
|
||||
|
||||
void getBounds(class AABox& out) const;
|
||||
|
||||
bool intersects(const Sphere& other) const;
|
||||
|
||||
/** Translates the sphere */
|
||||
Sphere operator+(const Vector3& v) const {
|
||||
return Sphere(center + v, radius);
|
||||
}
|
||||
|
||||
/** Translates the sphere */
|
||||
Sphere operator-(const Vector3& v) const {
|
||||
return Sphere(center - v, radius);
|
||||
}
|
||||
|
||||
/** Sets this to the smallest sphere that encapsulates both */
|
||||
void merge(const Sphere& s);
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
inline unsigned int hashCode(const G3D::Sphere& sphere) {
|
||||
return (unsigned int)(hashCode(sphere.center) + (sphere.radius * 13));
|
||||
}
|
||||
|
||||
template <> struct HashTrait<G3D::Sphere> {
|
||||
static size_t hashCode(const G3D::Sphere& key) {
|
||||
return static_cast<size_t>(key.center.hashCode() + (key.radius * 13));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
|||
367
dep/include/g3dlite/G3D/Spline.h
Normal file
367
dep/include/g3dlite/G3D/Spline.h
Normal file
|
|
@ -0,0 +1,367 @@
|
|||
/**
|
||||
@file Spline.h
|
||||
|
||||
@author Morgan McGuire, http://graphics.cs.williams.edu
|
||||
*/
|
||||
|
||||
#ifndef G3D_SPLINE_H
|
||||
#define G3D_SPLINE_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Array.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/Matrix4.h"
|
||||
#include "G3D/Vector4.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/** Common implementation code for all G3D::Spline template parameters */
|
||||
class SplineBase {
|
||||
public:
|
||||
|
||||
/** Times at which control points occur. Must have the same
|
||||
number of elements as Spline::control. */
|
||||
Array<float> time;
|
||||
|
||||
/** If cyclic, then the control points will be assumed to wrap around.
|
||||
If not cyclic, then the tangents at the ends of the spline
|
||||
point to the final control points.*/
|
||||
bool cyclic;
|
||||
|
||||
/** For a cyclic spline, this is the time elapsed between the last
|
||||
control point and the first. If less than or equal to zero this is
|
||||
assumed to be:
|
||||
|
||||
(time[0] - time[1] + .
|
||||
time[time.size() - 1] - time[time.size() - 2]) / 2.
|
||||
*/
|
||||
float finalInterval;
|
||||
|
||||
SplineBase() : cyclic(true), finalInterval(-1) {}
|
||||
|
||||
virtual ~SplineBase() {}
|
||||
|
||||
/** See specification for Spline::finalInterval; this handles the
|
||||
non-positive case. Returns 0 if not cyclic. */
|
||||
float getFinalInterval() const;
|
||||
|
||||
/** Returns the amount of time covered by this spline in one
|
||||
period. For a cyclic spline, this contains the final
|
||||
interval.*/
|
||||
float duration() const;
|
||||
|
||||
/** Computes the derivative spline basis from the control point version. */
|
||||
static Matrix4 computeBasis();
|
||||
|
||||
protected:
|
||||
|
||||
/** Assumes that t0 <= s < tn. called by computeIndex. */
|
||||
void computeIndexInBounds(float s, int& i, float& u) const;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
Given a time @a s, finds @a i and 0 <= @a u < 1 such that
|
||||
@a s = time[@a i] * @a u + time[@a i + 1] * (1 - @a u). Note that
|
||||
@a i may be outside the bounds of the time and control arrays;
|
||||
use getControl to handle wraparound and extrapolation issues.
|
||||
|
||||
This function takes expected O(1) time for control points with
|
||||
uniform time sampled control points or for uniformly
|
||||
distributed random time samples, but may take O( log time.size() ) time
|
||||
in the worst case.
|
||||
|
||||
Called from evaluate().
|
||||
*/
|
||||
void computeIndex(float s, int& i, float& u) const;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Smooth parameteric curve implemented using a piecewise 3rd-order
|
||||
Catmull-Rom spline curve. The spline is considered infinite and may
|
||||
either continue linearly from the specified control points or cycle
|
||||
through them. Control points are spaced uniformly in time at unit
|
||||
intervals by default, but irregular spacing may be explicitly
|
||||
specified.
|
||||
|
||||
The dimension of the spline can be set by varying the Control
|
||||
template parameter. For a 1D function, use Spline<float>. For a
|
||||
curve in the plane, Spline<Vector2>. Note that <i>any</i> template
|
||||
parameter that supports operator+(Control) and operator*(float) can
|
||||
be used; you can make splines out of G3D::Vector4, G3D::Matrix3, or
|
||||
your own classes.
|
||||
|
||||
To provide shortest-path interpolation, subclass G3D::Spline and
|
||||
override ensureShortestPath(). To provide normalization of
|
||||
interpolated points (e.g., projecting Quats onto the unit
|
||||
hypersphere) override correct().
|
||||
|
||||
See Real Time Rendering, 2nd edition, ch 12 for a general discussion
|
||||
of splines and their properties.
|
||||
|
||||
@sa G3D::UprightSpline, G3D::QuatSpline
|
||||
*/
|
||||
template<typename Control>
|
||||
class Spline : public SplineBase {
|
||||
protected:
|
||||
/** The additive identity control point. */
|
||||
Control zero;
|
||||
|
||||
public:
|
||||
|
||||
/** Control points. Must have the same number of elements as
|
||||
Spline::time.*/
|
||||
Array<Control> control;
|
||||
|
||||
Spline() {
|
||||
static Control x;
|
||||
// Hide the fact from C++ that we are using an
|
||||
// uninitialized variable here by pointer arithmetic.
|
||||
// This is ok because any type that is a legal control
|
||||
// point also supports multiplication by float.
|
||||
zero = *(&x) * 0.0f;
|
||||
}
|
||||
|
||||
/** Appends a control point at a specific time that must be
|
||||
greater than that of the previous point. */
|
||||
void append(float t, const Control& c) {
|
||||
debugAssertM((time.size() == 0) || (t > time.last()),
|
||||
"Control points must have monotonically increasing times.");
|
||||
time.append(t);
|
||||
control.append(c);
|
||||
debugAssert(control.size() == time.size());
|
||||
}
|
||||
|
||||
|
||||
/** Appends control point spaced in time based on the previous
|
||||
control point, or spaced at unit intervals if this is the
|
||||
first control point. */
|
||||
void append(const Control& c) {
|
||||
switch (time.size()) {
|
||||
case 0:
|
||||
append(0, c);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if (time[0] == 0) {
|
||||
append(1, c);
|
||||
} else {
|
||||
append(time[0], c);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
append(2 * time[time.size() - 1] - time[time.size() - 2], c);
|
||||
}
|
||||
debugAssert(control.size() == time.size());
|
||||
}
|
||||
|
||||
/** Erases all control points and times, but retains the state of
|
||||
cyclic and finalInterval.
|
||||
*/
|
||||
void clear() {
|
||||
control.clear();
|
||||
time.clear();
|
||||
}
|
||||
|
||||
|
||||
/** Number of control points */
|
||||
int size() const {
|
||||
debugAssert(time.size() == control.size());
|
||||
return control.size();
|
||||
}
|
||||
|
||||
|
||||
/** Returns the requested control point and time sample based on
|
||||
array index. If the array index is out of bounds, wraps (for
|
||||
a cyclic spline) or linearly extrapolates (for a non-cyclic
|
||||
spline), assuming time intervals follow the first or last
|
||||
sample recorded.
|
||||
|
||||
Calls correct() on the control point if it was extrapolated.
|
||||
|
||||
Returns 0 if there are no control points.
|
||||
|
||||
@sa Spline::control and Spline::time for the underlying
|
||||
control point array; Spline::computeIndex to find the index
|
||||
given a time.
|
||||
*/
|
||||
void getControl(int i, float& t, Control& c) const {
|
||||
int N = control.size();
|
||||
if (N == 0) {
|
||||
c = zero;
|
||||
t = 0;
|
||||
} else if (cyclic) {
|
||||
c = control[iWrap(i, N)];
|
||||
|
||||
if (i < 0) {
|
||||
// Wrapped around bottom
|
||||
|
||||
// Number of times we wrapped around the cyclic array
|
||||
int wraps = (N + 1 - i) / N;
|
||||
int j = (i + wraps * N) % N;
|
||||
t = time[j] - wraps * duration();
|
||||
|
||||
} else if (i < N) {
|
||||
|
||||
t = time[i];
|
||||
|
||||
} else {
|
||||
// Wrapped around top
|
||||
|
||||
// Number of times we wrapped around the cyclic array
|
||||
int wraps = i / N;
|
||||
int j = i % N;
|
||||
t = time[j] + wraps * duration();
|
||||
}
|
||||
|
||||
} else if (i < 0) {
|
||||
// Are there enough points to extrapolate?
|
||||
if (N >= 2) {
|
||||
// Step away from control point 0
|
||||
float dt = time[1] - time[0];
|
||||
|
||||
// Extrapolate (note; i is negative)
|
||||
c = control[1] * float(i) + control[0] * float(1 - i);
|
||||
correct(c);
|
||||
t = dt * i + time[0];
|
||||
|
||||
} else {
|
||||
// Just clamp
|
||||
c = control[0];
|
||||
|
||||
// Only 1 time; assume 1s intervals
|
||||
t = time[0] + i;
|
||||
}
|
||||
|
||||
} else if (i >= N) {
|
||||
if (N >= 2) {
|
||||
float dt = time[N - 1] - time[N - 2];
|
||||
|
||||
// Extrapolate
|
||||
c = control[N - 1] * float(i - N + 2) + control[N - 2] * -float(i - N + 1);
|
||||
correct(c);
|
||||
t = time[N - 1] + dt * (i - N + 1);
|
||||
|
||||
} else {
|
||||
// Return the last, clamping
|
||||
c = control.last();
|
||||
// Only 1 time; assume 1s intervals
|
||||
t = time[0] + i;
|
||||
}
|
||||
} else {
|
||||
// In bounds
|
||||
c = control[i];
|
||||
t = time[i];
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/** Returns a series of N control points and times, fixing
|
||||
boundary issues. The indices may be assumed to be treated
|
||||
cyclically. */
|
||||
void getControls(int i, float* T, Control* A, int N) const {
|
||||
for (int j = 0; j < N; ++j) {
|
||||
getControl(i + j, T[j], A[j]);
|
||||
}
|
||||
ensureShortestPath(A, N);
|
||||
}
|
||||
|
||||
/**
|
||||
Mutates the array of N control points. It is useful to override this
|
||||
method by one that wraps the values if they are angles or quaternions
|
||||
for which "shortest path" interpolation is significant.
|
||||
*/
|
||||
virtual void ensureShortestPath(Control* A, int N) const { (void)A; (void) N;}
|
||||
|
||||
/** Normalize or otherwise adjust this interpolated Control. */
|
||||
virtual void correct(Control& A) const { (void)A; }
|
||||
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
Return the position at time s. The spline is defined outside
|
||||
of the time samples by extrapolation or cycling.
|
||||
*/
|
||||
Control evaluate(float s) const {
|
||||
debugAssertM(control.size() == time.size(), "Corrupt spline: wrong number of control points.");
|
||||
|
||||
/*
|
||||
@cite http://www.gamedev.net/reference/articles/article1497.asp
|
||||
Derivation of basis matrix follows.
|
||||
|
||||
Given control points with positions p[i] at times t[i], 0 <= i <= 3, find the position
|
||||
at time t[1] <= s <= t[2].
|
||||
|
||||
Let u = s - t[0]
|
||||
Let U = [u^0 u^1 u^2 u^3] = [1 u u^2 u^3]
|
||||
Let dt0 = t[0] - t[-1]
|
||||
Let dt1 = t[1] - t[0]
|
||||
Let dt2 = t[2] - t[1]
|
||||
*/
|
||||
|
||||
// Index of the first control point (i.e., the u = 0 point)
|
||||
int i = 0;
|
||||
// Fractional part of the time
|
||||
float u = 0;
|
||||
|
||||
computeIndex(s, i, u);
|
||||
|
||||
Control p[4];
|
||||
float t[4];
|
||||
getControls(i - 1, t, p, 4);
|
||||
float dt0 = t[1] - t[0];
|
||||
float dt1 = t[2] - t[1];
|
||||
float dt2 = t[3] - t[2];
|
||||
|
||||
static const Matrix4 basis = computeBasis();
|
||||
|
||||
// Powers of u
|
||||
Vector4 uvec((float)(u*u*u), (float)(u*u), (float)u, 1.0f);
|
||||
|
||||
// Compute the weights on each of the control points.
|
||||
const Vector4& weights = uvec * basis;
|
||||
|
||||
// Compute the weighted sum of the neighboring control points.
|
||||
Control sum;
|
||||
|
||||
const Control& p0 = p[0];
|
||||
const Control& p1 = p[1];
|
||||
const Control& p2 = p[2];
|
||||
const Control& p3 = p[3];
|
||||
|
||||
const Control& dp0 = p1 + (p0*-1.0f);
|
||||
const Control& dp1 = p2 + (p1*-1.0f);
|
||||
const Control& dp2 = p3 + (p2*-1.0f);
|
||||
|
||||
// The factor of 1/2 from averaging two time intervals is
|
||||
// already factored into the basis
|
||||
|
||||
// tan1 = (dp0 / dt0 + dp1 / dt1) * ((dt0 + dt1) * 0.5);
|
||||
// The last term normalizes for unequal time intervals
|
||||
float x = (dt0 + dt1) * 0.5f;
|
||||
float n0 = x / dt0;
|
||||
float n1 = x / dt1;
|
||||
float n2 = x / dt2;
|
||||
const Control& dp1n1 = dp1 * n1;
|
||||
const Control& tan1 = dp0 * n0 + dp1n1;
|
||||
const Control& tan2 = dp1n1 + dp2 * n2;
|
||||
|
||||
sum =
|
||||
tan1 * weights[0]+
|
||||
p1 * weights[1] +
|
||||
p2 * weights[2] +
|
||||
tan2 * weights[3];
|
||||
|
||||
|
||||
correct(sum);
|
||||
return sum;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
144
dep/include/g3dlite/G3D/Stopwatch.h
Normal file
144
dep/include/g3dlite/G3D/Stopwatch.h
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
/**
|
||||
@file Stopwatch.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2005-10-05
|
||||
@edited 2009-05-10
|
||||
|
||||
Copyright 2000-2009, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_Stopwatch_h
|
||||
#define G3D_Stopwatch_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Queue.h"
|
||||
#include "G3D/G3DGameUnits.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
\brief Accurately measure durations and framerates.
|
||||
|
||||
Example 1: For profiling code in the context of a rendering loop:
|
||||
<pre>
|
||||
sw.tick();
|
||||
...timed code...
|
||||
sw.tock();
|
||||
|
||||
screenPrintf("%f\n", sw.smoothFPS());
|
||||
</pre>
|
||||
|
||||
|
||||
Example 2: For profiling pieces of a sequence:
|
||||
<pre>
|
||||
Stopwatch sw;
|
||||
slowOperation();
|
||||
sw.after("slowOperation");
|
||||
kdTree.balance();
|
||||
sw.after("Balance tree");
|
||||
</pre>
|
||||
*/
|
||||
class Stopwatch {
|
||||
private:
|
||||
|
||||
std::string myName;
|
||||
double startTime;
|
||||
std::string prevMark;
|
||||
double prevTime;
|
||||
|
||||
/** True between tick and tock */
|
||||
bool inBetween;
|
||||
|
||||
/** The initial cycle count. */
|
||||
uint64 cycleStart;
|
||||
|
||||
/** The time at which tick was called. */
|
||||
RealTime timeStart;
|
||||
|
||||
/** The time at which the previous tock was called, -1 if never. */
|
||||
RealTime lastTockTime;
|
||||
|
||||
RealTime lastDuration;
|
||||
int64 lastCycleCount;
|
||||
|
||||
/** Frames per second. */
|
||||
double m_fps;
|
||||
|
||||
/** Weighted fps */
|
||||
double emwaFPS;
|
||||
double m_smoothFPS;
|
||||
|
||||
/** Weighted duration */
|
||||
RealTime emwaDuration;
|
||||
|
||||
/** The overhead for calling into the class. */
|
||||
int64 cycleOverhead;
|
||||
|
||||
/** Called from the constructor. */
|
||||
void computeOverhead();
|
||||
|
||||
public:
|
||||
|
||||
Stopwatch(const std::string& name = "Stopwatch");
|
||||
|
||||
/** Returns the number of times that tick was called per wall-clock second;
|
||||
e.g. frames-per-second. */
|
||||
double FPS() const {
|
||||
return m_fps;
|
||||
}
|
||||
|
||||
/** Amount of time between the most recent tick and tock calls. 0 if tick has
|
||||
never been called. */
|
||||
RealTime elapsedTime() const {
|
||||
return lastDuration;
|
||||
}
|
||||
|
||||
/** Time-smoothed value that is stable to the nearest 1%.
|
||||
This is useful if you are displaying elapsed time in real-time
|
||||
and want a stable number.*/
|
||||
RealTime smoothElapsedTime() const {
|
||||
return emwaDuration;
|
||||
}
|
||||
|
||||
/** Time-smoothed value of fps that is stable to the nearest integer for fps > 10 and
|
||||
to the first decimal place for fps <= 10.
|
||||
This is useful if you
|
||||
are displaying the frame rate in real-time and want a stable (readable) number.*/
|
||||
double smoothFPS() const {
|
||||
return m_smoothFPS;
|
||||
}
|
||||
|
||||
/** The elapsed cycle time between tick and tock. An attempt is made to factor out all
|
||||
tick/tock overhead, so that back-to-back calls should return zero.
|
||||
Unreliable on non-x86 platforms.*/
|
||||
uint64 elapsedCycles() const {
|
||||
return lastCycleCount;
|
||||
}
|
||||
|
||||
/** Call at the beginning of the period that you want timed. */
|
||||
void tick();
|
||||
|
||||
/** Call at the end of the period that you want timed. */
|
||||
void tock();
|
||||
|
||||
|
||||
/** Reset the start time used by after() and the emwa value.*/
|
||||
void reset();
|
||||
|
||||
/** Call after an operation has completed, with the name of the operation, to
|
||||
print a debug message listing the time since the previous after() call. */
|
||||
void after(const std::string& s = "");
|
||||
|
||||
};
|
||||
|
||||
/** Because it is hard to remember the proper capitalization. */
|
||||
typedef Stopwatch StopWatch;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,92 +1,278 @@
|
|||
/**
|
||||
/**
|
||||
@file System.h
|
||||
|
||||
@maintainer Morgan McGuire, matrix@graphics3d.com
|
||||
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@cite Rob Wyatt http://www.gamasutra.com/features/wyatts_world/19990709/processor_detection_01.htm
|
||||
@cite Benjamin Jurke http://www.flipcode.com/cgi-bin/msg.cgi?showThread=COTD-ProcessorDetectionClass&forum=cotd&id=-1
|
||||
@cite Michael Herf http://www.stereopsis.com/memcpy.html
|
||||
|
||||
@created 2003-01-25
|
||||
@edited 2006-04-26
|
||||
@edited 2008-10-14
|
||||
*/
|
||||
|
||||
#ifndef G3D_SYSTEM_H
|
||||
#define G3D_SYSTEM_H
|
||||
#ifndef G3D_System_h
|
||||
#define G3D_System_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/G3DGameUnits.h"
|
||||
#include "G3D/BinaryFormat.h"
|
||||
#include <string>
|
||||
|
||||
#ifdef G3D_OSX
|
||||
# include <CoreServices/CoreServices.h>
|
||||
# include <CoreServices/CoreServices.h>
|
||||
#endif
|
||||
|
||||
|
||||
namespace G3D {
|
||||
|
||||
typedef double RealTime;
|
||||
/**
|
||||
Routine used by the demos to find the data. Searches in
|
||||
../data, ../../data, etc. up to 5 levels back. Checks
|
||||
common locations like \verbatim c:\libraries\g3d-<version>\data \endverbatim
|
||||
and some hard-coded paths on the Brown University file
|
||||
system.
|
||||
|
||||
@deprecated
|
||||
*/
|
||||
std::string demoFindData(bool errorIfNotFound = true);
|
||||
|
||||
/** G3D, SDL, and IJG libraries require license documentation
|
||||
to be distributed with your program. This generates the
|
||||
string that must appear in your documentation.
|
||||
<B>Your program can be commercial, closed-source</B> under
|
||||
any license you want.
|
||||
@deprecated Use System::license
|
||||
*/
|
||||
std::string license();
|
||||
|
||||
/**
|
||||
@brief The order in which the bytes of an integer are stored on a
|
||||
machine.
|
||||
|
||||
Intel/AMD chips tend to be G3D_LITTLE_ENDIAN, Mac PPC's and Suns are
|
||||
G3D_BIG_ENDIAN. However, this is primarily used to specify the byte
|
||||
order of file formats, which are fixed.
|
||||
*/
|
||||
enum G3DEndian {
|
||||
G3D_BIG_ENDIAN,
|
||||
G3D_LITTLE_ENDIAN
|
||||
};
|
||||
|
||||
/**
|
||||
@brief OS and processor abstraction.
|
||||
|
||||
The first time any method is called the processor will be analyzed.
|
||||
Future calls are then fast.
|
||||
|
||||
Timing function overview:
|
||||
System::getCycleCount
|
||||
- actual cycle count
|
||||
|
||||
System::getTick
|
||||
- High-resolution time in seconds since program started
|
||||
|
||||
System::getLocalTime
|
||||
- High-resolution time in seconds since Jan 1, 1970
|
||||
(because it is stored in a double, this may be less
|
||||
accurate than getTick)
|
||||
*/
|
||||
class System {
|
||||
public:
|
||||
|
||||
/** Called automatically by the other System routines.*/
|
||||
static void init();
|
||||
|
||||
/**
|
||||
Guarantees that the start of the array is aligned to the
|
||||
specified number of bytes.
|
||||
*/
|
||||
static void* alignedMalloc(size_t bytes, size_t alignment);
|
||||
@param size Size of memory that the system was trying to allocate
|
||||
|
||||
/**
|
||||
Uses pooled storage to optimize small allocations (1 byte to 5 kilobytes).
|
||||
Can be 10x to 100x faster than calling ::malloc or new.
|
||||
@param recoverable If true, the system will attempt to allocate again
|
||||
if the callback returns true. If false, malloc is going to return
|
||||
NULL and this invocation is just to notify the application.
|
||||
|
||||
The result must be freed with free.
|
||||
|
||||
Threadsafe on Win32.
|
||||
|
||||
@sa calloc realloc OutOfMemoryCallback free
|
||||
*/
|
||||
static void* malloc(size_t bytes);
|
||||
|
||||
static void* calloc(size_t n, size_t x);
|
||||
|
||||
/**
|
||||
@param size Size of memory that the system was trying to allocate
|
||||
@param recoverable If true, the system will attempt to allocate again
|
||||
if the callback returns true. If false, malloc is going to return
|
||||
NULL and this invocation is just to notify the application.
|
||||
@return Return true to force malloc to attempt allocation again if the
|
||||
error was recoverable.
|
||||
@return Return true to force malloc to attempt allocation again if the
|
||||
error was recoverable.
|
||||
*/
|
||||
typedef bool (*OutOfMemoryCallback)(size_t size, bool recoverable);
|
||||
|
||||
/**
|
||||
When System::malloc fails to allocate memory because the system is
|
||||
out of memory, it invokes this handler (if it is not NULL).
|
||||
The argument to the callback is the amount of memory that malloc
|
||||
was trying to allocate when it ran out. If the callback returns
|
||||
true, System::malloc will attempt to allocate the memory again.
|
||||
If the callback returns false, then System::malloc will return NULL.
|
||||
private:
|
||||
|
||||
You can use outOfMemoryCallback to free data structures or to
|
||||
register the failure.
|
||||
bool m_initialized;
|
||||
int m_cpuSpeed;
|
||||
bool m_hasCPUID;
|
||||
bool m_hasRDTSC;
|
||||
bool m_hasMMX;
|
||||
bool m_hasSSE;
|
||||
bool m_hasSSE2;
|
||||
bool m_hasSSE3;
|
||||
bool m_has3DNOW;
|
||||
bool m_has3DNOW2;
|
||||
bool m_hasAMDMMX;
|
||||
std::string m_cpuVendor;
|
||||
int m_numCores;
|
||||
|
||||
/** this holds the data directory set by the application (currently
|
||||
GApp) for use by findDataFile */
|
||||
std::string m_appDataDir;
|
||||
|
||||
G3DEndian m_machineEndian;
|
||||
std::string m_cpuArch;
|
||||
std::string m_operatingSystem;
|
||||
|
||||
# ifdef G3D_WIN32
|
||||
/** Used by getTick() for timing */
|
||||
LARGE_INTEGER m_start;
|
||||
LARGE_INTEGER m_counterFrequency;
|
||||
#else
|
||||
struct timeval m_start;
|
||||
#endif
|
||||
|
||||
std::string m_version;
|
||||
OutOfMemoryCallback m_outOfMemoryCallback;
|
||||
|
||||
#ifdef G3D_OSX
|
||||
/** In Cycles/Second */
|
||||
SInt32 m_OSXCPUSpeed;
|
||||
double m_secondsPerNS;
|
||||
#endif
|
||||
|
||||
/** The Real-World time of System::getTick() time 0. Set by initTime */
|
||||
RealTime m_realWorldGetTickTime0;
|
||||
|
||||
uint32 m_highestCPUIDFunction;
|
||||
|
||||
/** @brief Used for the singleton instance only. */
|
||||
System();
|
||||
|
||||
/** @brief The singleton instance.
|
||||
|
||||
Used instead of a global variable to ensure that the order of
|
||||
intialization is correct, which is critical because other
|
||||
globals may allocate memory using System::malloc.
|
||||
*/
|
||||
static OutOfMemoryCallback outOfMemoryCallback;
|
||||
static System& instance();
|
||||
|
||||
enum CPUIDFunction {
|
||||
CPUID_VENDOR_ID = 0x00000000,
|
||||
CPUID_PROCESSOR_FEATURES = 0x00000001,
|
||||
CPUID_NUM_CORES = 0x00000004,
|
||||
CPUID_GET_HIGHEST_FUNCTION = 0x80000000,
|
||||
CPUID_EXTENDED_FEATURES = 0x80000001};
|
||||
|
||||
/** Helper macro to call cpuid functions and return all values
|
||||
|
||||
See http://software.intel.com/en-us/articles/intel-64-architecture-processor-topology-enumeration/
|
||||
or http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/25481.pdf
|
||||
|
||||
for description of the arguments.
|
||||
*/
|
||||
static void cpuid(CPUIDFunction func, uint32& areg, uint32& breg, uint32& creg, uint32& dreg);
|
||||
|
||||
void init();
|
||||
|
||||
/** Called from init() */
|
||||
void getStandardProcessorExtensions();
|
||||
|
||||
/** Called from init() */
|
||||
void initTime();
|
||||
|
||||
public:
|
||||
|
||||
/** Returns the speed of processor 0 in MHz.
|
||||
Always returns 0 on linux.*/
|
||||
inline static int cpuSpeedMHz() {
|
||||
return instance().m_cpuSpeed;
|
||||
}
|
||||
|
||||
/** Returns the number of logical processor cores (i.e., the
|
||||
number of execution units for threads) */
|
||||
inline static int numCores() {
|
||||
return instance().m_numCores;
|
||||
}
|
||||
|
||||
inline static bool hasCPUID() {
|
||||
return instance().m_hasCPUID;
|
||||
}
|
||||
|
||||
inline static bool hasRDTSC() {
|
||||
return instance().m_hasRDTSC;
|
||||
}
|
||||
|
||||
inline static bool hasSSE() {
|
||||
return instance().m_hasSSE;
|
||||
}
|
||||
|
||||
inline static bool hasSSE2() {
|
||||
return instance().m_hasSSE2;
|
||||
}
|
||||
|
||||
inline static bool hasSSE3() {
|
||||
return instance().m_hasSSE3;
|
||||
}
|
||||
|
||||
inline static bool hasMMX() {
|
||||
return instance().m_hasMMX;
|
||||
}
|
||||
|
||||
inline static bool has3DNow() {
|
||||
return instance().m_has3DNOW;
|
||||
}
|
||||
|
||||
inline static const std::string& cpuVendor() {
|
||||
return instance().m_cpuVendor;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the endianness of this machine.
|
||||
*/
|
||||
inline static G3DEndian machineEndian() {
|
||||
return instance().m_machineEndian;
|
||||
}
|
||||
|
||||
/** e.g., "Windows", "GNU/Linux" */
|
||||
inline static const std::string& operatingSystem() {
|
||||
return instance().m_operatingSystem;
|
||||
}
|
||||
|
||||
/** e.g., 80686 */
|
||||
inline static const std::string& cpuArchitecture() {
|
||||
return instance().m_cpuArch;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the current date as a string in the form YYYY-MM-DD
|
||||
*/
|
||||
static std::string currentDateString();
|
||||
|
||||
/**
|
||||
Guarantees that the start of the array is aligned to the
|
||||
specified number of bytes.
|
||||
*/
|
||||
static void* alignedMalloc(size_t bytes, size_t alignment);
|
||||
|
||||
/**
|
||||
Uses pooled storage to optimize small allocations (1 byte to 5
|
||||
kilobytes). Can be 10x to 100x faster than calling ::malloc or
|
||||
new.
|
||||
|
||||
The result must be freed with free.
|
||||
|
||||
Threadsafe on Win32.
|
||||
|
||||
@sa calloc realloc OutOfMemoryCallback free
|
||||
*/
|
||||
static void* malloc(size_t bytes);
|
||||
|
||||
static void* calloc(size_t n, size_t x);
|
||||
|
||||
/**
|
||||
Version of realloc that works with System::malloc.
|
||||
*/
|
||||
static void* realloc(void* block, size_t bytes);
|
||||
|
||||
/** Returns a string describing how well System::malloc is using its internal pooled storage.
|
||||
"heap" memory was slow to allocate; the other data sizes are comparatively fast.*/
|
||||
/** Returns a string describing how well System::malloc is using
|
||||
its internal pooled storage. "heap" memory was slow to
|
||||
allocate; the other data sizes are comparatively fast.*/
|
||||
static std::string mallocPerformance();
|
||||
static void resetMallocPerformanceCounters();
|
||||
|
||||
/**
|
||||
/**
|
||||
Returns a string describing the current usage of the buffer pools used for
|
||||
optimizing System::malloc.
|
||||
*/
|
||||
|
|
@ -105,17 +291,216 @@ public:
|
|||
static void alignedFree(void* ptr);
|
||||
|
||||
/** An implementation of memcpy that may be up to 2x as fast as the C library
|
||||
one on some processors. Guaranteed to have the same behavior as memcpy
|
||||
in all cases. */
|
||||
one on some processors. Guaranteed to have the same behavior as memcpy
|
||||
in all cases. */
|
||||
static void memcpy(void* dst, const void* src, size_t numBytes);
|
||||
|
||||
/** An implementation of memset that may be up to 2x as fast as the C library
|
||||
one on some processors. Guaranteed to have the same behavior as memset
|
||||
in all cases. */
|
||||
one on some processors. Guaranteed to have the same behavior as memset
|
||||
in all cases. */
|
||||
static void memset(void* dst, uint8 value, size_t numBytes);
|
||||
|
||||
/**
|
||||
Returns the fully qualified filename for the currently running executable.
|
||||
|
||||
This is more reliable than arg[0], which may be intentionally set
|
||||
to an incorrect value by a calling program, relative to a now
|
||||
non-current directory, or obfuscated by sym-links.
|
||||
|
||||
@cite Linux version written by Nicolai Haehnle <prefect_@gmx.net>, http://www.flipcode.com/cgi-bin/msg.cgi?showThread=COTD-getexename&forum=cotd&id=-1
|
||||
*/
|
||||
static std::string currentProgramFilename();
|
||||
|
||||
/** Name of this program. Note that you can mutate this string to
|
||||
set your app name explicitly.*/
|
||||
static std::string& appName();
|
||||
|
||||
/** G3D Version string */
|
||||
inline static const std::string& version() {
|
||||
return instance().m_version;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief The optimization status of the G3D library (not the program compiled against it)
|
||||
|
||||
Either "Debug" or "Release", depending on whether _DEBUG was
|
||||
defined at compile-time for the library.
|
||||
*/
|
||||
static const std::string& build();
|
||||
|
||||
/**
|
||||
Causes the current thread to yield for the specified duration
|
||||
and consume almost no CPU.
|
||||
The sleep will be extremely precise; it uses System::time()
|
||||
to calibrate the exact yeild time.
|
||||
*/
|
||||
static void sleep(RealTime t);
|
||||
|
||||
/**
|
||||
Clears the console.
|
||||
Console programs only.
|
||||
*/
|
||||
static void consoleClearScreen();
|
||||
|
||||
/**
|
||||
Returns true if a key is waiting.
|
||||
Console programs only.
|
||||
*/
|
||||
static bool consoleKeyPressed();
|
||||
|
||||
/**
|
||||
Blocks until a key is read (use consoleKeyPressed to determine if
|
||||
a key is waiting to be read) then returns the character code for
|
||||
that key.
|
||||
*/
|
||||
static int consoleReadKey();
|
||||
|
||||
/**
|
||||
The actual time (measured in seconds since
|
||||
Jan 1 1970 midnight).
|
||||
|
||||
Adjusted for local timezone and daylight savings
|
||||
time. This is as accurate and fast as getCycleCount().
|
||||
*/
|
||||
static RealTime time();
|
||||
|
||||
/**
|
||||
To count the number of cycles a given operation takes:
|
||||
|
||||
<PRE>
|
||||
unsigned long count;
|
||||
System::beginCycleCount(count);
|
||||
...
|
||||
System::endCycleCount(count);
|
||||
// count now contains the cycle count for the intervening operation.
|
||||
</PRE>
|
||||
*/
|
||||
/* static void beginCycleCount(uint64& cycleCount);
|
||||
static void endCycleCount(uint64& cycleCount);
|
||||
|
||||
static uint64 getCycleCount(); */
|
||||
|
||||
inline static void setOutOfMemoryCallback(OutOfMemoryCallback c) {
|
||||
instance().m_outOfMemoryCallback = c;
|
||||
}
|
||||
|
||||
/**
|
||||
When System::malloc fails to allocate memory because the system is
|
||||
out of memory, it invokes this handler (if it is not NULL).
|
||||
The argument to the callback is the amount of memory that malloc
|
||||
was trying to allocate when it ran out. If the callback returns
|
||||
true, System::malloc will attempt to allocate the memory again.
|
||||
If the callback returns false, then System::malloc will return NULL.
|
||||
|
||||
You can use outOfMemoryCallback to free data structures or to
|
||||
register the failure.
|
||||
*/
|
||||
inline static OutOfMemoryCallback outOfMemoryCallback() {
|
||||
return instance().m_outOfMemoryCallback;
|
||||
}
|
||||
|
||||
/** Set an environment variable for the current process */
|
||||
static void setEnv(const std::string& name, const std::string& value);
|
||||
|
||||
/** Get an environment variable for the current process. Returns NULL if the variable doesn't exist. */
|
||||
static const char* getEnv(const std::string& name);
|
||||
|
||||
/**
|
||||
Prints a human-readable description of this machine
|
||||
to the text output stream. Either argument may be NULL.
|
||||
*/
|
||||
static void describeSystem(
|
||||
class TextOutput& t);
|
||||
|
||||
static void describeSystem(
|
||||
std::string& s);
|
||||
|
||||
/** On Win32, returns the clipboard text contents. Does nothing on other
|
||||
platforms (yet) */
|
||||
static std::string getClipboardText();
|
||||
|
||||
/** Copies the text to the clipboard on Win32. */
|
||||
static void setClipboardText(const std::string& s);
|
||||
|
||||
/**
|
||||
Tries to locate the resource by looking in related directories.
|
||||
If found, returns the full path to the resource, otherwise
|
||||
returns the empty string.
|
||||
*/
|
||||
static std::string findDataFile(const std::string& full, bool errorIfNotFound = true);
|
||||
|
||||
/**
|
||||
Sets the path that the application is using as its data directory.
|
||||
Used by findDataDir as an initial search location. GApp sets this
|
||||
upon constrution.
|
||||
*/
|
||||
static void setAppDataDir(const std::string& path);
|
||||
|
||||
};
|
||||
|
||||
/* don't need that for MaNGOS, not portable to Win64...
|
||||
#ifdef _MSC_VER
|
||||
inline uint64 System::getCycleCount() {
|
||||
uint32 timehi, timelo;
|
||||
|
||||
// Use the assembly instruction rdtsc, which gets the current
|
||||
// cycle count (since the process started) and puts it in edx:eax.
|
||||
__asm
|
||||
{
|
||||
rdtsc;
|
||||
mov timehi, edx;
|
||||
mov timelo, eax;
|
||||
}
|
||||
|
||||
return ((uint64)timehi << 32) + (uint64)timelo;
|
||||
}
|
||||
|
||||
#elif defined(G3D_LINUX)
|
||||
|
||||
inline uint64 System::getCycleCount() {
|
||||
uint32 timehi, timelo;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
"rdtsc "
|
||||
: "=a" (timelo),
|
||||
"=d" (timehi)
|
||||
: );
|
||||
|
||||
return ((uint64)timehi << 32) + (uint64)timelo;
|
||||
}
|
||||
|
||||
#elif defined(G3D_OSX)
|
||||
|
||||
inline uint64 System::getCycleCount() {
|
||||
//Note: To put off extra processing until the end, this does not
|
||||
//return the actual clock cycle count. It is a bus cycle count.
|
||||
//When endCycleCount() is called, it converts the two into a difference
|
||||
//of clock cycles
|
||||
|
||||
return (uint64) UnsignedWideToUInt64(UpTime());
|
||||
//return (uint64) mach_absolute_time();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
inline void System::beginCycleCount(uint64& cycleCount) {
|
||||
cycleCount = getCycleCount();
|
||||
}
|
||||
|
||||
|
||||
inline void System::endCycleCount(uint64& cycleCount) {
|
||||
#ifndef G3D_OSX
|
||||
cycleCount = getCycleCount() - cycleCount;
|
||||
#else
|
||||
AbsoluteTime end = UpTime();
|
||||
Nanoseconds diffNS =
|
||||
AbsoluteDeltaToNanoseconds(end, UInt64ToUnsignedWide(cycleCount));
|
||||
cycleCount =
|
||||
(uint64) ((double) (instance().m_OSXCPUSpeed) *
|
||||
(double) UnsignedWideToUInt64(diffNS) * instance().m_secondsPerNS);
|
||||
#endif
|
||||
}
|
||||
*/
|
||||
|
||||
} // namespace
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
801
dep/include/g3dlite/G3D/TextInput.h
Normal file
801
dep/include/g3dlite/G3D/TextInput.h
Normal file
|
|
@ -0,0 +1,801 @@
|
|||
/**
|
||||
@file TextInput.h
|
||||
|
||||
Simple text lexer/tokenizer.
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@cite Based on a lexer written by Aaron Orenstein.
|
||||
|
||||
@created 2002-11-27
|
||||
@edited 2009-11-24
|
||||
|
||||
Copyright 2000-2009, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_TextInput_h
|
||||
#define G3D_TextInput_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Array.h"
|
||||
#include "G3D/Set.h"
|
||||
#include "G3D/ParseError.h"
|
||||
#include <string>
|
||||
#include <queue>
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
For use with TextInput.
|
||||
*/
|
||||
class Token {
|
||||
public:
|
||||
|
||||
/**
|
||||
More detailed type information than Type.
|
||||
*/
|
||||
enum ExtendedType {
|
||||
DOUBLE_QUOTED_TYPE,
|
||||
SINGLE_QUOTED_TYPE,
|
||||
SYMBOL_TYPE,
|
||||
FLOATING_POINT_TYPE,
|
||||
INTEGER_TYPE,
|
||||
BOOLEAN_TYPE,
|
||||
LINE_COMMENT_TYPE,
|
||||
BLOCK_COMMENT_TYPE,
|
||||
NEWLINE_TYPE,
|
||||
END_TYPE
|
||||
};
|
||||
|
||||
/**
|
||||
Strings are enclosed in quotes, symbols are not.
|
||||
*/
|
||||
enum Type {
|
||||
STRING = DOUBLE_QUOTED_TYPE,
|
||||
SYMBOL = SYMBOL_TYPE,
|
||||
NUMBER = FLOATING_POINT_TYPE,
|
||||
BOOLEAN = BOOLEAN_TYPE,
|
||||
COMMENT = LINE_COMMENT_TYPE,
|
||||
NEWLINE = NEWLINE_TYPE,
|
||||
END = END_TYPE
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
friend class TextInput;
|
||||
|
||||
/**
|
||||
Holds the actual value, which might be any type. If a number, it will be
|
||||
parsed at runtime.
|
||||
*/
|
||||
std::string _string;
|
||||
|
||||
bool _bool;
|
||||
int _line;
|
||||
int _character;
|
||||
Type _type;
|
||||
ExtendedType _extendedType;
|
||||
|
||||
public:
|
||||
|
||||
Token() :
|
||||
_string(""),
|
||||
_bool(false),
|
||||
_line(0),
|
||||
_character(0),
|
||||
_type(END),
|
||||
_extendedType(END_TYPE) {}
|
||||
|
||||
Token(Type t, ExtendedType e, const std::string& s, int L, int c)
|
||||
: _string(s), _bool(false), _line(L), _character(c), _type(t), _extendedType(e) {}
|
||||
|
||||
Token(Type t, ExtendedType e, const std::string& s, bool b, int L, int c)
|
||||
: _string(s), _bool(b), _line(L), _character(c), _type(t), _extendedType(e) {}
|
||||
|
||||
Type type() const {
|
||||
return _type;
|
||||
}
|
||||
|
||||
ExtendedType extendedType() const {
|
||||
return _extendedType;
|
||||
}
|
||||
|
||||
/**
|
||||
The value of a single or double quote string (not including the quotes),
|
||||
the name of a symbol, or the exact textual representation of a number as
|
||||
parsed from the input.
|
||||
*/
|
||||
const std::string& string() const {
|
||||
return _string;
|
||||
}
|
||||
|
||||
bool boolean() const {
|
||||
return _bool;
|
||||
}
|
||||
|
||||
/**
|
||||
Starting line of the input from which this token was parsed. Starts
|
||||
at 1.
|
||||
*/
|
||||
int line() const {
|
||||
return _line;
|
||||
}
|
||||
|
||||
/**
|
||||
Starting character position in the input line from which this token was
|
||||
parsed. Starts at 1.
|
||||
*/
|
||||
int character() const {
|
||||
return _character;
|
||||
}
|
||||
|
||||
/** Return the numeric value for a number type, or zero if this is
|
||||
not a number type.
|
||||
*/
|
||||
double number() const;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
A simple style tokenizer for reading text files. TextInput handles a
|
||||
superset of C++,Java, Matlab, and Bash code text including single
|
||||
line comments, block comments, quoted strings with escape sequences,
|
||||
and operators. TextInput recognizes several categories of tokens,
|
||||
which are separated by white space, quotation marks, or the end of a
|
||||
recognized operator:
|
||||
|
||||
<ul>
|
||||
<li><CODE>Token::SINGLE_QUOTED_TYPE</CODE> string of characters surrounded by single quotes, e.g., 'x', '\\0', 'foo'.
|
||||
<li><CODE>Token::DOUBLE_QUOTED_TYPE</CODE> string of characters surrounded by double quotes, e.g., "x", "abc\txyz", "b o b".
|
||||
<li><CODE>Token::SYMBOL_TYPE</CODE> legal C++ operators, keywords, and identifiers. e.g., >=, Foo, _X, class, {
|
||||
<li><CODE>Token::INTEGER_TYPE</CODE> numbers without decimal places or exponential notation. e.g., 10, 0x17F, 32, 0, -155
|
||||
<li><CODE>Token::FLOATING_POINT_TYPE</CODE> numbers with decimal places or exponential notation. e.g., 1e3, -1.2, .4, 0.5
|
||||
<li><CODE>Token::BOOLEAN_TYPE</CODE> special symbols like "true" and "false"; the exact details can be configured in TextInput::Settings
|
||||
<li><CODE>Token::LINE_COMMENT_TYPE</CODE> (disabled by default); generated for line comments as specified by TextInput::Settings
|
||||
<li><CODE>Token::BLOCK_COMMENT_TYPE</CODE> (disabled by default); generated for c-style block comments as specified by TextInput::Settings
|
||||
<li><CODE>Token::NEWLINE_TYPE</CODE> (disabled by default); generated for any of "\\r", "\\n" or "\\r\\n"
|
||||
</ul>
|
||||
|
||||
<P>The special ".." and "..." tokens are always recognized in
|
||||
addition to normal C++ operators. Additional tokens can be made
|
||||
available by changing the Settings.
|
||||
|
||||
Negative numbers are handled specially because of the ambiguity between unary minus and negative numbers--
|
||||
see the note on TextInput::read.
|
||||
|
||||
TextInput does not have helper functions for types with non-obvious
|
||||
formatting, or helpers that would be redundant. Use the serialize
|
||||
methods instead for parsing specific types like int, Vector3, and
|
||||
Color3.
|
||||
|
||||
Inside quoted strings escape sequences are converted. Thus the
|
||||
string token for ["a\\nb"] is 'a', followed by a newline, followed by
|
||||
'b'. Outside of quoted strings, escape sequences are not converted,
|
||||
so the token sequence for [a\\nb] is symbol 'a', symbol '\\', symbol
|
||||
'nb' (this matches what a C++ parser would do). The exception is
|
||||
that a specified TextInput::Settings::otherCommentCharacter preceeded
|
||||
by a backslash is assumed to be an escaped comment character and is
|
||||
returned as a symbol token instead of being parsed as a comment
|
||||
(this is what a LaTex or VRML parser would do).
|
||||
|
||||
<B>Examples</B>
|
||||
|
||||
<PRE>
|
||||
TextInput ti(TextInput::FROM_STRING, "name = \"Max\", height = 6");
|
||||
|
||||
Token t;
|
||||
|
||||
t = ti.read();
|
||||
debugAssert(t.type == Token::SYMBOL);
|
||||
debugAssert(t.sval == "name");
|
||||
|
||||
ti.read();
|
||||
debugAssert(t.type == Token::SYMBOL);
|
||||
debugAssert(t.sval == "=");
|
||||
|
||||
std::string name = ti.read().sval;
|
||||
ti.read();
|
||||
</PRE>
|
||||
|
||||
<PRE>
|
||||
TextInput ti(TextInput::FROM_STRING, "name = \"Max\", height = 6");
|
||||
ti.readSymbols("name", "=");
|
||||
std::string name = ti.readString();
|
||||
ti.readSymbols(",", "height", "=");
|
||||
double height = ti. readNumber();
|
||||
</PRE>
|
||||
|
||||
Assumes that the file is not modified once opened.
|
||||
*/
|
||||
class TextInput {
|
||||
public:
|
||||
|
||||
/** Tokenizer configuration options. */
|
||||
class Settings {
|
||||
public:
|
||||
/** If true, C-style slash-star marks a multi-line comment.
|
||||
|
||||
See generateCommentTokens for rules on how this is applied.
|
||||
|
||||
Default is true.
|
||||
*/
|
||||
bool cppBlockComments;
|
||||
|
||||
/** If true, // begins a single line comment.
|
||||
|
||||
See generateCommentTokens for rules on how this is applied.
|
||||
|
||||
Default is true.
|
||||
*/
|
||||
bool cppLineComments;
|
||||
|
||||
/** If true, otherCommentCharacter and otherCommentCharacter2
|
||||
are used to begin single line comments in the same way
|
||||
cppLineComments is.
|
||||
|
||||
See generateCommentTokens for rules on how this is applied.
|
||||
|
||||
Default is true.
|
||||
*/
|
||||
bool otherLineComments;
|
||||
|
||||
/** If true, \\r, \\n, \\t, \\0, \\\\ and other escape sequences inside
|
||||
strings are converted to the equivalent C++ escaped character.
|
||||
If false, backslashes are treated literally. It is convenient to
|
||||
set to false if reading Windows paths, for example, like
|
||||
c:\\foo\\bar.
|
||||
|
||||
Default is true.
|
||||
*/
|
||||
bool escapeSequencesInStrings;
|
||||
|
||||
/** If not '\\0', specifies a character that begins single line
|
||||
comments ('#' and '%' are popular choices). This is independent
|
||||
of the cppLineComments flag. If the character appears in text with
|
||||
a backslash in front of it, it is considered escaped and is not
|
||||
treated as a comment character.
|
||||
|
||||
Default is '\\0'.
|
||||
*/
|
||||
char otherCommentCharacter;
|
||||
|
||||
/** Another (optional) 1-comment character. Useful for files that
|
||||
support multiple comment syntaxes. Default is '\\0'.
|
||||
*/
|
||||
char otherCommentCharacter2;
|
||||
|
||||
/** If true, comments enabled by cppBlockComments, cppLineComments
|
||||
and otherLineComments will generate their respective tokens.
|
||||
If false, the same settings will enable parsing and ignoring
|
||||
comments
|
||||
|
||||
Default is false.
|
||||
*/
|
||||
bool generateCommentTokens;
|
||||
|
||||
/** If true, newlines will generate tokens.
|
||||
If false, newlines will be discarded as whitespace when parsed
|
||||
outside of other tokens.
|
||||
|
||||
Default is false.
|
||||
*/
|
||||
bool generateNewlineTokens;
|
||||
|
||||
/** If true, "-1" parses as the number -1 instead of the
|
||||
symbol "-" followed by the number 1. Default is true.*/
|
||||
bool signedNumbers;
|
||||
|
||||
/** If true, strings can be marked with single quotes (e.g.,
|
||||
'aaa'). If false, the quote character is parsed as a
|
||||
symbol. Default is true. Backquote (`) is always parsed
|
||||
as a symbol. */
|
||||
bool singleQuotedStrings;
|
||||
|
||||
/** The character to use as a single quote. Defaults to "'" (backquote),
|
||||
occasionally useful to set to "`" (forward quote) or to "," (comma) for
|
||||
reading CSV files. */
|
||||
char singleQuoteCharacter;
|
||||
|
||||
/** If set to a non-empty string, that string will be used in
|
||||
place of the real file name (or in place of a pseudonym
|
||||
constructed from the buffer if given FROM_STRING) in
|
||||
tokens and exceptions.
|
||||
|
||||
Default is empty.
|
||||
*/
|
||||
std::string sourceFileName;
|
||||
|
||||
|
||||
/** Added to the line number reported by peekLineNumber and in
|
||||
exceptions. Useful for concatenating files that are
|
||||
parsed separately. Default is zero. */
|
||||
int startingLineNumberOffset;
|
||||
|
||||
/**
|
||||
Parse -1.#IND00 as the floating point number returned by
|
||||
nan(), -1.#INF00 as -inf(), and 1.#INF00 as inf(). Note
|
||||
that the C99 standard specifies that a variety of formats
|
||||
like "NaN" and "nan" are to be used; these are easier to
|
||||
parse yourself and not currently supported by readNumber.
|
||||
|
||||
An alternative to specifying msvcSpecials is to read numbers as:
|
||||
<pre>
|
||||
Token x = t.read();
|
||||
Token y = t.peek();
|
||||
if ((x.string() == "-1.") &&
|
||||
(y.string() == "#INF00") &&
|
||||
(y.character() == x.character() + 3) &&
|
||||
(y.line() == x.line()) {
|
||||
t.read();
|
||||
return nan();
|
||||
}
|
||||
// ... similar cases for inf
|
||||
</pre>
|
||||
|
||||
If the single-comment character was #, the floating point
|
||||
special format overrides the comment and will be parsed
|
||||
instead.
|
||||
|
||||
If signedNumbers is false msvcSpecials will not be parsed.
|
||||
|
||||
Default is true. */
|
||||
bool msvcSpecials;
|
||||
|
||||
/**
|
||||
Parse the following set of useful proof symbols:
|
||||
|
||||
=>
|
||||
::>
|
||||
<::
|
||||
:>
|
||||
<:
|
||||
|-
|
||||
::=
|
||||
:=
|
||||
<-
|
||||
|
||||
Default is false.
|
||||
*/
|
||||
bool proofSymbols;
|
||||
|
||||
/**
|
||||
When parsing booleans and msvcSpecials, is case significant?
|
||||
Default is {true}
|
||||
*/
|
||||
bool caseSensitive;
|
||||
|
||||
/** All symbols that will become the 'true' boolean token. See also caseSensitive.
|
||||
Clear this value to disable parsing of true booleans.
|
||||
|
||||
Default is {true}.
|
||||
*/
|
||||
Set<std::string> trueSymbols;
|
||||
|
||||
/** See trueSymbols. Default is {false}*/
|
||||
Set<std::string> falseSymbols;
|
||||
|
||||
Settings();
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
std::deque<Token> stack;
|
||||
|
||||
/**
|
||||
Characters to be tokenized.
|
||||
*/
|
||||
Array<char> buffer;
|
||||
|
||||
/**
|
||||
Offset of current character (the next character to consumed) in
|
||||
input buffer.
|
||||
*/
|
||||
int currentCharOffset;
|
||||
|
||||
/**
|
||||
Line number of next character to be consumed from the input buffer. (1
|
||||
indicates first line of input.)
|
||||
|
||||
Note that this is the line number of the @e next character to be
|
||||
consumed from the input, not the line number of the @e last character
|
||||
consumed!
|
||||
*/
|
||||
int lineNumber;
|
||||
|
||||
/**
|
||||
Character number (within the line) of the next character to be consumed
|
||||
from the input buffer. (1 indicates first character of the line).
|
||||
|
||||
Note that this is the character number of the @e next character to be
|
||||
consumed from the input, not the character number of the @e last
|
||||
character consumed!
|
||||
*/
|
||||
int charNumber;
|
||||
|
||||
/** Configuration options. This includes the file name that will be
|
||||
reported in tokens and exceptions. */
|
||||
Settings options;
|
||||
|
||||
void init();
|
||||
|
||||
/**
|
||||
Consumes the next character from the input buffer, and returns that
|
||||
character. Updates lineNumber and charNumber to reflect the location of
|
||||
the next character in the input buffer.
|
||||
|
||||
Note: you shouldn't be using the return value of this function in most
|
||||
cases. In general, you should peekInputChar() to get the next
|
||||
character, determine what to do with it, then consume it with this
|
||||
function (or with eatAndPeekInputChar()). Given that usage, in most
|
||||
instances you already know what this function would return!
|
||||
*/
|
||||
int eatInputChar();
|
||||
|
||||
/**
|
||||
Returns the next character from the input buffer, without consuming any
|
||||
characters. Can also be used to look deeper into the input buffer.
|
||||
Does not modify lineNumber or charNumber.
|
||||
|
||||
@param distance Index of the character in the input buffer to peek at,
|
||||
relative to the next character. Default is 0, for the next character in
|
||||
the input buffer.
|
||||
*/
|
||||
int peekInputChar(int distance = 0);
|
||||
|
||||
/**
|
||||
Helper function to consume the next character in the input buffer and
|
||||
peek at the one following (without consuming it).
|
||||
*/
|
||||
inline int eatAndPeekInputChar() {
|
||||
eatInputChar();
|
||||
return peekInputChar(0);
|
||||
}
|
||||
|
||||
/**
|
||||
Read the next token, returning an END token if no more input is
|
||||
available.
|
||||
*/
|
||||
Token nextToken();
|
||||
|
||||
/**
|
||||
Helper for nextToken. Appends characters to t._string until the end
|
||||
delimiter is reached.
|
||||
|
||||
When called, the next character in the input buffer should be first the
|
||||
first character after the opening delimiter character.
|
||||
*/
|
||||
void parseQuotedString(unsigned char delimiter, Token& t);
|
||||
|
||||
public:
|
||||
|
||||
class TokenException : public ParseError {
|
||||
public:
|
||||
/** Name of file being parsed when exception occurred.
|
||||
\deprecated Use filename
|
||||
*/
|
||||
std::string sourceFile;
|
||||
|
||||
virtual ~TokenException() {}
|
||||
|
||||
protected:
|
||||
|
||||
TokenException(
|
||||
const std::string& src,
|
||||
int ln,
|
||||
int ch);
|
||||
|
||||
};
|
||||
|
||||
/** While parsing a number of the form 1.\#IN?00, ? was
|
||||
not 'D' or 'F'. */
|
||||
class BadMSVCSpecial : public TokenException {
|
||||
public:
|
||||
|
||||
BadMSVCSpecial(
|
||||
const std::string& src,
|
||||
int ln,
|
||||
int ch);
|
||||
};
|
||||
|
||||
/** Thrown by the read methods. */
|
||||
class WrongTokenType : public TokenException {
|
||||
public:
|
||||
Token::Type expected;
|
||||
Token::Type actual;
|
||||
|
||||
WrongTokenType(
|
||||
const std::string& src,
|
||||
int ln,
|
||||
int ch,
|
||||
Token::Type e,
|
||||
Token::Type a);
|
||||
};
|
||||
|
||||
class WrongSymbol : public TokenException {
|
||||
public:
|
||||
std::string expected;
|
||||
std::string actual;
|
||||
|
||||
WrongSymbol(
|
||||
const std::string& src,
|
||||
int ln,
|
||||
int ch,
|
||||
const std::string& e,
|
||||
const std::string& a);
|
||||
};
|
||||
|
||||
|
||||
/** String read from input did not match expected string. */
|
||||
class WrongString : public TokenException {
|
||||
public:
|
||||
std::string expected;
|
||||
std::string actual;
|
||||
|
||||
WrongString(
|
||||
const std::string& src,
|
||||
int ln,
|
||||
int ch,
|
||||
const std::string& e,
|
||||
const std::string& a);
|
||||
};
|
||||
|
||||
TextInput(const std::string& filename, const Settings& settings = Settings());
|
||||
|
||||
enum FS {FROM_STRING};
|
||||
/** Creates input directly from a string. The first argument must be
|
||||
TextInput::FROM_STRING.
|
||||
*/
|
||||
TextInput(FS fs, const std::string& str, const Settings& settings = Settings());
|
||||
|
||||
/** Returns true while there are tokens remaining. */
|
||||
bool hasMore();
|
||||
|
||||
/** Read the next token (which will be the END token if ! hasMore()).
|
||||
|
||||
Signed numbers can be handled in one of two modes. If the option
|
||||
TextInput::Settings::signedNumbers is true,
|
||||
A '+' or '-' immediately before a number is prepended onto that number and
|
||||
if there is intervening whitespace, it is read as a separate symbol.
|
||||
|
||||
If TextInput::Settings::signedNumbers is false,
|
||||
read() does not distinguish between a plus or minus symbol next
|
||||
to a number and a positive/negative number itself. For example, "x - 1" and "x -1"
|
||||
will be parsed the same way by read().
|
||||
|
||||
In both cases, readNumber() will contract a leading "-" or "+" onto
|
||||
a number.
|
||||
*/
|
||||
Token read();
|
||||
|
||||
/** Calls read() until the result is not a newline or comment */
|
||||
Token readSignificant();
|
||||
|
||||
/** Read one token (or possibly two) as a number or throws
|
||||
WrongTokenType, and returns the number.
|
||||
|
||||
If the first token in the input is a number, it is returned directly.
|
||||
|
||||
If TextInput::Settings::signedNumbers is false and the input stream
|
||||
contains a '+' or '-' symbol token immediately followed by a number
|
||||
token, both tokens will be consumed and a single token will be
|
||||
returned by this method.
|
||||
|
||||
WrongTokenType will be thrown if one of the input conditions
|
||||
described above is not satisfied. When an exception is thrown, no
|
||||
tokens are consumed.
|
||||
*/
|
||||
double readNumber();
|
||||
|
||||
bool readBoolean();
|
||||
|
||||
/** Reads a string token or throws WrongTokenType, and returns the token.
|
||||
|
||||
Use this method (rather than readString) if you want the token's
|
||||
location as well as its value.
|
||||
|
||||
WrongTokenType will be thrown if the next token in the input stream
|
||||
is not a string. When an exception is thrown, no tokens are
|
||||
consumed.
|
||||
*/
|
||||
Token readStringToken();
|
||||
|
||||
/** Like readStringToken, but returns the token's string.
|
||||
|
||||
Use this method (rather than readStringToken) if you want the token's
|
||||
value but don't really care about its location in the input. Use of
|
||||
readStringToken is encouraged for better error reporting.
|
||||
*/
|
||||
std::string readString();
|
||||
|
||||
/** Reads a specific string token or throws either WrongTokenType or
|
||||
WrongString. If the next token in the input is a string matching @p
|
||||
s, it will be consumed.
|
||||
|
||||
Use this method if you want to match a specific string from the
|
||||
input. In that case, typically error reporting related to the token
|
||||
is only going to occur because of a mismatch, so no location
|
||||
information is needed by the caller.
|
||||
|
||||
WrongTokenType will be thrown if the next token in the input stream
|
||||
is not a string. WrongString will be thrown if the next token in the
|
||||
input stream is a string but does not match the @p s parameter. When
|
||||
an exception is thrown, no tokens are consumed.
|
||||
*/
|
||||
void readString(const std::string& s);
|
||||
|
||||
/** Reads a comment token or throws WrongTokenType, and returns the token.
|
||||
|
||||
Use this method (rather than readComment) if you want the token's
|
||||
location as well as its value.
|
||||
|
||||
WrongTokenType will be thrown if the next token in the input stream
|
||||
is not a comment. When an exception is thrown, no tokens are
|
||||
consumed.
|
||||
*/
|
||||
Token readCommentToken();
|
||||
|
||||
/** Like readCommentToken, but returns the token's string.
|
||||
|
||||
Use this method (rather than readCommentToken) if you want the token's
|
||||
value but don't really care about its location in the input. Use of
|
||||
readCommentToken is encouraged for better error reporting.
|
||||
*/
|
||||
std::string readComment();
|
||||
|
||||
/** Reads a specific comment token or throws either WrongTokenType or
|
||||
WrongString. If the next token in the input is a comment matching @p
|
||||
s, it will be consumed.
|
||||
|
||||
Use this method if you want to match a specific comment from the
|
||||
input. In that case, typically error reporting related to the token
|
||||
is only going to occur because of a mismatch, so no location
|
||||
information is needed by the caller.
|
||||
|
||||
WrongTokenType will be thrown if the next token in the input stream
|
||||
is not a comment. WrongString will be thrown if the next token in the
|
||||
input stream is a comment but does not match the @p s parameter. When
|
||||
an exception is thrown, no tokens are consumed.
|
||||
*/
|
||||
void readComment(const std::string& s);
|
||||
|
||||
/** Reads a newline token or throws WrongTokenType, and returns the token.
|
||||
|
||||
Use this method (rather than readNewline) if you want the token's
|
||||
location as well as its value.
|
||||
|
||||
WrongTokenType will be thrown if the next token in the input stream
|
||||
is not a newline. When an exception is thrown, no tokens are
|
||||
consumed.
|
||||
*/
|
||||
Token readNewlineToken();
|
||||
|
||||
/** Like readNewlineToken, but returns the token's string.
|
||||
|
||||
Use this method (rather than readNewlineToken) if you want the token's
|
||||
value but don't really care about its location in the input. Use of
|
||||
readNewlineToken is encouraged for better error reporting.
|
||||
*/
|
||||
std::string readNewline();
|
||||
|
||||
/** Reads a specific newline token or throws either WrongTokenType or
|
||||
WrongString. If the next token in the input is a newline matching @p
|
||||
s, it will be consumed.
|
||||
|
||||
Use this method if you want to match a specific newline from the
|
||||
input. In that case, typically error reporting related to the token
|
||||
is only going to occur because of a mismatch, so no location
|
||||
information is needed by the caller.
|
||||
|
||||
WrongTokenType will be thrown if the next token in the input stream
|
||||
is not a newline. WrongString will be thrown if the next token in the
|
||||
input stream is a newlin but does not match the @p s parameter. When
|
||||
an exception is thrown, no tokens are consumed.
|
||||
*/
|
||||
void readNewline(const std::string& s);
|
||||
|
||||
/** Reads a symbol token or throws WrongTokenType, and returns the token.
|
||||
|
||||
Use this method (rather than readSymbol) if you want the token's
|
||||
location as well as its value.
|
||||
|
||||
WrongTokenType will be thrown if the next token in the input stream
|
||||
is not a symbol. When an exception is thrown, no tokens are
|
||||
consumed.
|
||||
*/
|
||||
Token readSymbolToken();
|
||||
|
||||
/** Like readSymbolToken, but returns the token's string.
|
||||
|
||||
Use this method (rather than readSymbolToken) if you want the token's
|
||||
value but don't really care about its location in the input. Use of
|
||||
readSymbolToken is encouraged for better error reporting.
|
||||
*/
|
||||
std::string readSymbol();
|
||||
|
||||
/** Reads a specific symbol token or throws either WrongTokenType or
|
||||
WrongSymbol. If the next token in the input is a symbol matching @p
|
||||
symbol, it will be consumed.
|
||||
|
||||
Use this method if you want to match a specific symbol from the
|
||||
input. In that case, typically error reporting related to the token
|
||||
is only going to occur because of a mismatch, so no location
|
||||
information is needed by the caller.
|
||||
|
||||
WrongTokenType will be thrown if the next token in the input stream
|
||||
is not a symbol. WrongSymbol will be thrown if the next token in the
|
||||
input stream is a symbol but does not match the @p symbol parameter.
|
||||
When an exception is thrown, no tokens are consumed.
|
||||
*/
|
||||
void readSymbol(const std::string& symbol);
|
||||
|
||||
|
||||
/** Read a series of two specific symbols. See readSymbol. */
|
||||
inline void readSymbols(const std::string& s1, const std::string& s2) {
|
||||
readSymbol(s1);
|
||||
readSymbol(s2);
|
||||
}
|
||||
|
||||
/** Read a series of three specific symbols. See readSymbol. */
|
||||
inline void readSymbols(
|
||||
const std::string& s1,
|
||||
const std::string& s2,
|
||||
const std::string& s3) {
|
||||
readSymbol(s1);
|
||||
readSymbol(s2);
|
||||
readSymbol(s3);
|
||||
}
|
||||
|
||||
/** Read a series of four specific symbols. See readSymbol. */
|
||||
inline void readSymbols(
|
||||
const std::string& s1,
|
||||
const std::string& s2,
|
||||
const std::string& s3,
|
||||
const std::string& s4) {
|
||||
readSymbol(s1);
|
||||
readSymbol(s2);
|
||||
readSymbol(s3);
|
||||
readSymbol(s4);
|
||||
}
|
||||
|
||||
/** Return a copy of the next token in the input stream, but don't remove
|
||||
it from the input stream.
|
||||
*/
|
||||
Token peek();
|
||||
|
||||
/** Returns the line number for the @e next token. See also peek. */
|
||||
int peekLineNumber();
|
||||
|
||||
/** Returns the character number (relative to the line) for the @e next
|
||||
token in the input stream. See also peek.
|
||||
*/
|
||||
int peekCharacterNumber();
|
||||
|
||||
/** Take a previously read token and push it back at the front of the
|
||||
input stream.
|
||||
|
||||
Can be used in the case where more than one token of read-ahead is
|
||||
needed (i.e., when peek doesn't suffice).
|
||||
*/
|
||||
void push(const Token& t);
|
||||
|
||||
/** Returns the filename from which this input is drawn, or the first few
|
||||
characters of the string if created from a string.
|
||||
If settings::filename is non-empty that will replace the
|
||||
true filename.*/
|
||||
const std::string& filename() const;
|
||||
};
|
||||
|
||||
void deserialize(bool& b, TextInput& ti);
|
||||
void deserialize(int& b, TextInput& ti);
|
||||
void deserialize(uint8& b, TextInput& ti);
|
||||
void deserialize(double& b, TextInput& ti);
|
||||
void deserialize(float& b, TextInput& ti);
|
||||
void deserialize(std::string& b, TextInput& ti);
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
|
||||
249
dep/include/g3dlite/G3D/TextOutput.h
Normal file
249
dep/include/g3dlite/G3D/TextOutput.h
Normal file
|
|
@ -0,0 +1,249 @@
|
|||
/**
|
||||
@file TextOutput.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
@created 2004-06-21
|
||||
@edited 2006-10-24
|
||||
|
||||
Copyright 2000-2007, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_TEXTOUTPUT_H
|
||||
#define G3D_TEXTOUTPUT_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Array.h"
|
||||
#include <string>
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
Convenient formatting of ASCII text written to a file.
|
||||
<P>
|
||||
|
||||
The core writeString, writeNumber, and writeSymbol methods map to TextInput's
|
||||
methods. Number and Symbol each print an additional space that is used to
|
||||
separate adjacent tokens.
|
||||
|
||||
TextOutput::printf allows arbitrary text to be conveniently dumped
|
||||
en-masse. Use [de]serialize(bool, TextOutput) and other overloads to read/write
|
||||
primitive types in a standardized manner and
|
||||
|
||||
<P>
|
||||
When a word-wrap line break occurs, all whitespace between words is replaced
|
||||
with a single newline (the newline may be two characters-- see
|
||||
G3D::TextOutput::Options::NewlineStyle). Word wrapping occurs against
|
||||
the number of columns specified by Options::numColumns, <I>minus</I> the current
|
||||
indent level.
|
||||
|
||||
Indenting adds the specified number of spaces immediately after a newline.
|
||||
If a newline was followed by spaces in the original string, these are added
|
||||
to the indent spaces. Indenting <B>will</B> indent blank lines and will leave
|
||||
indents after the last newline of a file (if the indent level is non-zero at the end).
|
||||
|
||||
<P><B>Serialization/Marshalling</B>
|
||||
<DT>Text serialization is accomplished using TextOutput by defining the pair of
|
||||
methods:
|
||||
|
||||
<PRE>
|
||||
void serialize(TextOutput& to) const;
|
||||
void deserialize(TextInput& ti);
|
||||
</PRE>
|
||||
|
||||
See also G3D::TextInput.
|
||||
|
||||
<P>
|
||||
<B>BETA API</B>
|
||||
<DT>This API is subject to change in future versions.
|
||||
*/
|
||||
class TextOutput {
|
||||
public:
|
||||
|
||||
class Settings {
|
||||
public:
|
||||
/**
|
||||
WRAP_NONE Word wrapping is disabled
|
||||
WRAP_WITHOUT_BREAKING Word-wrap, but don't break continuous lines that
|
||||
are longer than numColumns (default)
|
||||
WRAP_ALWAYS Wrap even if it means breaking a continuous line or
|
||||
a quoted string.
|
||||
|
||||
Word wrapping is only allowed at whitespaces ('\\n', '\\r', '\\t', ' '); it
|
||||
will not occur after commas, punctuation, minus signs, or any other characters
|
||||
*/
|
||||
enum WordWrapMode {WRAP_NONE, WRAP_WITHOUT_BREAKING, WRAP_ALWAYS};
|
||||
|
||||
/** Defaults to WRAP_WITHOUT_BREAKING */
|
||||
WordWrapMode wordWrap;
|
||||
|
||||
/** Is word-wrapping allowed to insert newlines inside double quotes?
|
||||
Default: false */
|
||||
bool allowWordWrapInsideDoubleQuotes;
|
||||
|
||||
/** Number of columns for word wrapping. Default: 8 */
|
||||
int numColumns;
|
||||
|
||||
/** Number of spaces in each indent. Default: 4 */
|
||||
int spacesPerIndent;
|
||||
|
||||
/** Style of newline used by word wrapping and by (optional) conversion.
|
||||
default: Windows: NEWLINE_WINDOWS, Linux, OS X: NEWLINE_UNIX.
|
||||
*/
|
||||
enum NewlineStyle {NEWLINE_WINDOWS, NEWLINE_UNIX};
|
||||
|
||||
NewlineStyle newlineStyle;
|
||||
|
||||
/** If true, all newlines are converted to NewlineStyle regardless of
|
||||
how they start out. Default: true. */
|
||||
bool convertNewlines;
|
||||
|
||||
/** Used by writeBoolean */
|
||||
std::string trueSymbol;
|
||||
|
||||
/** Used by writeBoolean */
|
||||
std::string falseSymbol;
|
||||
|
||||
Settings() :
|
||||
wordWrap(WRAP_WITHOUT_BREAKING),
|
||||
allowWordWrapInsideDoubleQuotes(false),
|
||||
numColumns(80),
|
||||
spacesPerIndent(4),
|
||||
convertNewlines(true),
|
||||
trueSymbol("true"),
|
||||
falseSymbol("false") {
|
||||
#ifdef G3D_WIN32
|
||||
newlineStyle = NEWLINE_WINDOWS;
|
||||
#else
|
||||
newlineStyle = NEWLINE_UNIX;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
/** Used by indentAndAppend to tell when we are writing the
|
||||
first character of a new line.
|
||||
|
||||
So that push/popIndent work correctly, we cannot indent
|
||||
immediately after writing a newline. Instead we must
|
||||
indent on writing the first character <B>after</B> that
|
||||
newline.
|
||||
*/
|
||||
bool startingNewLine;
|
||||
|
||||
/** Number of characters at the end of the buffer since the last newline */
|
||||
int currentColumn;
|
||||
|
||||
/** True if we have seen an open " and no close ".*/
|
||||
bool inDQuote;
|
||||
|
||||
/** Empty if there is none */
|
||||
std::string filename;
|
||||
|
||||
Array<char> data;
|
||||
|
||||
Settings option;
|
||||
|
||||
/** Number of indents to prepend before each line. Always set using setIndentLevel.*/
|
||||
int indentLevel;
|
||||
|
||||
void setIndentLevel(int i);
|
||||
|
||||
/** Actual number of spaces to indent. */
|
||||
int indentSpaces;
|
||||
|
||||
/** the newline character(s) */
|
||||
std::string newline;
|
||||
|
||||
void setOptions(const Settings& _opt);
|
||||
|
||||
/** Converts to the desired newlines. Called from vprintf */
|
||||
void convertNewlines(const std::string& in, std::string& out);
|
||||
|
||||
/** Called from vprintf */
|
||||
void wordWrapIndentAppend(const std::string& str);
|
||||
|
||||
/** Appends the character to data, indenting whenever a newline is encountered.
|
||||
Called from wordWrapIndentAppend */
|
||||
void indentAppend(char c);
|
||||
|
||||
public:
|
||||
|
||||
explicit TextOutput(const std::string& filename, const Settings& options = Settings());
|
||||
|
||||
/** Constructs a text output that can later be commited to a string instead of a file.*/
|
||||
explicit TextOutput(const Settings& options = Settings());
|
||||
|
||||
/** Commit to the filename specified on the constructor.
|
||||
<B>Not</B> called from the destructor; you must call
|
||||
it yourself.
|
||||
@param flush If true (default) the file is ready for reading when the method returns, otherwise
|
||||
the method returns immediately and writes the file in the background.*/
|
||||
void commit(bool flush = true);
|
||||
|
||||
/** Commits to this string */
|
||||
void commitString(std::string& string);
|
||||
|
||||
/** Increase indent level by 1 */
|
||||
void pushIndent();
|
||||
|
||||
void popIndent();
|
||||
|
||||
/** Produces a new string that contains the output */
|
||||
std::string commitString();
|
||||
|
||||
/** Writes a quoted string. Special characters in the string (e.g., \\, \\t, \\n) are escaped so that
|
||||
TextInput will produce the identical string on reading.*/
|
||||
void writeString(const std::string& string);
|
||||
|
||||
void writeBoolean(bool b);
|
||||
|
||||
void writeNumber(double n);
|
||||
|
||||
void writeNumber(int n);
|
||||
|
||||
void writeNewline();
|
||||
void writeNewlines(int numLines);
|
||||
|
||||
/** The symbol is written without quotes. Symbols are required to begin with a
|
||||
letter or underscore and contain only letters, underscores, and numbers
|
||||
or be a C++ symbol (e.g. "{", "(", "++", etc.)
|
||||
so that they may be properly parsed by TextInput::readSymbol. Symbols are
|
||||
printed with a trailing space.*/
|
||||
void writeSymbol(const std::string& string);
|
||||
|
||||
/** Convenient idiom for writing multiple symbols in a row, e.g.
|
||||
writeSymbols("name", "="); The empty symbols are not written.
|
||||
*/
|
||||
void writeSymbols(
|
||||
const std::string& a,
|
||||
const std::string& b = "",
|
||||
const std::string& c = "",
|
||||
const std::string& d = "",
|
||||
const std::string& e = "",
|
||||
const std::string& f = "");
|
||||
|
||||
/** Normal printf conventions. Note that the output will be reformatted
|
||||
for word-wrapping and newlines */
|
||||
void __cdecl printf(const char* fmt, ...)
|
||||
G3D_CHECK_PRINTF_METHOD_ARGS;
|
||||
|
||||
// Can't pass by reference because that confuses va_start
|
||||
void __cdecl printf(const std::string fmt, ...);
|
||||
void __cdecl vprintf(const char* fmt, va_list argPtr)
|
||||
G3D_CHECK_VPRINTF_METHOD_ARGS;
|
||||
};
|
||||
|
||||
// Primitive serializers
|
||||
void serialize(const bool& b, TextOutput& to);
|
||||
void serialize(const int& b, TextOutput& to);
|
||||
void serialize(const uint8& b, TextOutput& to);
|
||||
void serialize(const double& b, TextOutput& to);
|
||||
void serialize(const float& b, TextOutput& to);
|
||||
void serialize(const std::string& b, TextOutput& to);
|
||||
void serialize(const char* b, TextOutput& to);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
87
dep/include/g3dlite/G3D/ThreadSet.h
Normal file
87
dep/include/g3dlite/G3D/ThreadSet.h
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
#ifndef G3D_THREADSET_H
|
||||
#define G3D_THREADSET_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Array.h"
|
||||
#include "G3D/ReferenceCount.h"
|
||||
#include "G3D/GThread.h"
|
||||
#include "G3D/GMutex.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/** Manages a set of threads. All methods are threadsafe except for
|
||||
the iterator begin/end.
|
||||
|
||||
@beta*/
|
||||
class ThreadSet : public ReferenceCountedObject {
|
||||
public:
|
||||
/** Intended to allow future use with a template parameter.*/
|
||||
typedef GThread Thread;
|
||||
|
||||
typedef ReferenceCountedPointer<Thread> ThreadRef;
|
||||
typedef ReferenceCountedPointer<ThreadSet> Ref;
|
||||
typedef Array<ThreadRef>::Iterator Iterator;
|
||||
typedef Array<ThreadRef>::ConstIterator ConstIterator;
|
||||
|
||||
private:
|
||||
|
||||
/** Protects m_thread */
|
||||
GMutex m_lock;
|
||||
|
||||
/** Threads in the set */
|
||||
Array<ThreadRef> m_thread;
|
||||
|
||||
public:
|
||||
|
||||
/** Total number of threads (some of which may be completed). */
|
||||
int size() const;
|
||||
|
||||
/** Number of threads that have been started */
|
||||
int numStarted() const;
|
||||
|
||||
/** Start all threads that are not currently started.
|
||||
|
||||
@param lastThreadBehavior If USE_CURRENT_THREAD, takes the last unstarted thread and executes it manually on
|
||||
the current thread. This helps to take full advantage of the machine when
|
||||
running a large number of jobs and avoids the overhead of a thread start for single-thread groups.
|
||||
Note that this forces start() to block until
|
||||
that thread is complete.
|
||||
*/
|
||||
void start(GThread::SpawnBehavior lastThreadBehavior = GThread::USE_NEW_THREAD) const;
|
||||
|
||||
/** Terminate all threads that are currently started */
|
||||
void terminate() const;
|
||||
|
||||
/** Waits until all started threads have completed. */
|
||||
void waitForCompletion() const;
|
||||
|
||||
/** Remove all (not stopping them) */
|
||||
void clear();
|
||||
|
||||
/** Removes completed threads and returns the new size.*/
|
||||
int removeCompleted();
|
||||
|
||||
/** Inserts a new thread, if it is not already present, and
|
||||
returns the new number of threads.*/
|
||||
int insert(const ThreadRef& t);
|
||||
|
||||
/** Removes a thread. Returns true if the thread was present and
|
||||
removed. */
|
||||
bool remove(const ThreadRef& t);
|
||||
|
||||
bool contains(const ThreadRef& t) const;
|
||||
|
||||
/** It is an error to mutate the ThreadSet while iterating through it. */
|
||||
Iterator begin();
|
||||
|
||||
Iterator end();
|
||||
|
||||
ConstIterator begin() const;
|
||||
|
||||
ConstIterator end() const;
|
||||
};
|
||||
|
||||
|
||||
} // namespace G3D
|
||||
|
||||
#endif
|
||||
|
|
@ -1,14 +1,14 @@
|
|||
/**
|
||||
@file Triangle.h
|
||||
|
||||
@maintainer Morgan McGuire, matrix@graphics3d.com
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2003-04-05
|
||||
@edited 2004-03-14
|
||||
@edited 2008-10-06
|
||||
|
||||
@cite Random point method by Greg Turk, Generating random points in triangles. In A. S. Glassner, ed., Graphics Gems, pp. 24-28. Academic Press, 1990
|
||||
|
||||
Copyright 2000-2006, Morgan McGuire.
|
||||
Copyright 2000-2009, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
|
@ -19,6 +19,8 @@
|
|||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/Vector3.h"
|
||||
#include "G3D/Plane.h"
|
||||
#include "G3D/BoundsTrait.h"
|
||||
#include "G3D/debugAssert.h"
|
||||
#include <string>
|
||||
|
||||
namespace G3D {
|
||||
|
|
@ -38,14 +40,15 @@ private:
|
|||
|
||||
/** edgeDirection[i] is the normalized vector v[i+1] - v[i] */
|
||||
Vector3 edgeDirection[3];
|
||||
double edgeMagnitude[3];
|
||||
float edgeMagnitude[3];
|
||||
Plane _plane;
|
||||
Vector3::Axis _primaryAxis;
|
||||
|
||||
/** vertex[1] - vertex[0] */
|
||||
Vector3 edge01;
|
||||
Vector3 _edge01;
|
||||
|
||||
/** vertex[2] - vertex[0] */
|
||||
Vector3 edge02;
|
||||
Vector3 _edge02;
|
||||
|
||||
float _area;
|
||||
|
||||
|
|
@ -53,6 +56,10 @@ private:
|
|||
|
||||
public:
|
||||
|
||||
Triangle(class BinaryInput& b);
|
||||
void serialize(class BinaryOutput& b);
|
||||
void deserialize(class BinaryInput& b);
|
||||
|
||||
Triangle();
|
||||
|
||||
Triangle(const Vector3& v0, const Vector3& v1, const Vector3& v2);
|
||||
|
|
@ -65,7 +72,17 @@ public:
|
|||
return _vertex[n];
|
||||
}
|
||||
|
||||
double area() const;
|
||||
/** vertex[1] - vertex[0] */
|
||||
inline const Vector3& edge01() const {
|
||||
return _edge01;
|
||||
}
|
||||
|
||||
/** vertex[2] - vertex[0] */
|
||||
inline const Vector3& edge02() const {
|
||||
return _edge02;
|
||||
}
|
||||
|
||||
float area() const;
|
||||
|
||||
Vector3::Axis primaryAxis() const {
|
||||
return _primaryAxis;
|
||||
|
|
@ -81,6 +98,13 @@ public:
|
|||
/** Returns a random point in the triangle. */
|
||||
Vector3 randomPoint() const;
|
||||
|
||||
inline void getRandomSurfacePoint
|
||||
(Vector3& P,
|
||||
Vector3& N = Vector3::ignore()) const {
|
||||
P = randomPoint();
|
||||
N = normal();
|
||||
}
|
||||
|
||||
/**
|
||||
For two triangles to be equal they must have
|
||||
the same vertices <I>in the same order</I>.
|
||||
|
|
@ -96,21 +120,41 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
inline unsigned int hashCode() const {
|
||||
inline size_t hashCode() const {
|
||||
return
|
||||
_vertex[0].hashCode() +
|
||||
(_vertex[1].hashCode() >> 2) +
|
||||
_vertex[2].hashCode();
|
||||
(_vertex[2].hashCode() >> 3);
|
||||
}
|
||||
|
||||
void getBounds(class AABox&) const;
|
||||
|
||||
/**
|
||||
@brief Intersect the ray at distance less than @a distance.
|
||||
|
||||
@param distance Set to the maximum distance (can be G3D::inf())
|
||||
to search for an intersection. On return, this is the smaller
|
||||
of the distance to the intersection, if one exists, and the original
|
||||
value.
|
||||
|
||||
@param baryCoord If a triangle is hit before @a distance, a
|
||||
the barycentric coordinates of the hit location on the triangle.
|
||||
Otherwise, unmodified.
|
||||
|
||||
@return True if there was an intersection before the original distance.
|
||||
*/
|
||||
bool intersect(const class Ray& ray, float& distance, float baryCoord[3]) const;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
} // namespace G3D
|
||||
|
||||
inline unsigned int hashCode(const G3D::Triangle& t) {
|
||||
return t.hashCode();
|
||||
}
|
||||
template <> struct HashTrait<G3D::Triangle> {
|
||||
static size_t hashCode(const G3D::Triangle& key) { return key.hashCode(); }
|
||||
};
|
||||
|
||||
|
||||
template<> struct BoundsTrait<class G3D::Triangle> {
|
||||
static void getBounds(const G3D::Triangle& t, G3D::AABox& out) { t.getBounds(out); }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
83
dep/include/g3dlite/G3D/UprightFrame.h
Normal file
83
dep/include/g3dlite/G3D/UprightFrame.h
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
/**
|
||||
@file UprightFrame.h
|
||||
|
||||
@author Morgan McGuire, http://graphics.cs.williams.edu
|
||||
*/
|
||||
|
||||
#ifndef G3D_UPRIGHTFRAME_H
|
||||
#define G3D_UPRIGHTFRAME_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Spline.h"
|
||||
#include "G3D/Vector3.h"
|
||||
#include "G3D/CoordinateFrame.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
Coordinate frame expressed in Euler angles.
|
||||
Unlike a G3D::Quat, UprightFrame always keeps the reference frame from rolling about its own z axis.
|
||||
Particularly useful for cameras.
|
||||
|
||||
@sa G3D::CoordinateFrame, G3D::Matrix4, G3D::PhysicsFrame, G3D::UprightSpline, G3D::UprightSplineManipulator
|
||||
*/
|
||||
class UprightFrame {
|
||||
public:
|
||||
|
||||
Vector3 translation;
|
||||
|
||||
/** -pi/2 < pitch < pi/2 in radians about the X-axis */
|
||||
float pitch;
|
||||
|
||||
/** In radians about the Y-axis */
|
||||
float yaw;
|
||||
|
||||
inline UprightFrame(const Vector3& t = Vector3::zero(), float p = 0, float y = 0)
|
||||
: translation(t), pitch(p), yaw(y) {}
|
||||
|
||||
UprightFrame(const CoordinateFrame& cframe);
|
||||
|
||||
CoordinateFrame toCoordinateFrame() const;
|
||||
|
||||
/** Supports implicit cast to CoordinateFrame */
|
||||
inline operator CoordinateFrame() const {
|
||||
return toCoordinateFrame();
|
||||
}
|
||||
|
||||
/** Required for use with spline */
|
||||
UprightFrame operator+(const UprightFrame& other) const;
|
||||
|
||||
/** Required for use with spline */
|
||||
UprightFrame operator*(const float k) const;
|
||||
|
||||
/**
|
||||
Unwraps the yaw values in the elements of the array such that
|
||||
they still represent the same angles but strictly increase/decrease
|
||||
without wrapping about zero. For use with Spline<UprightFrame>
|
||||
*/
|
||||
static void unwrapYaw(UprightFrame* a, int N);
|
||||
|
||||
void serialize(class BinaryOutput& b) const;
|
||||
void deserialize(class BinaryInput& b);
|
||||
};
|
||||
|
||||
/** Shortest-path linear velocity spline for camera positions. Always keeps the camera from rolling.
|
||||
@sa G3D::UprightSplineManipulator, G3D::UprightFrame
|
||||
*/
|
||||
class UprightSpline : public Spline<UprightFrame> {
|
||||
protected:
|
||||
|
||||
virtual void ensureShortestPath(UprightFrame* A, int N) const {
|
||||
UprightFrame::unwrapYaw(A, N);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
void serialize(class BinaryOutput& b) const;
|
||||
void deserialize(class BinaryInput& b);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -3,27 +3,33 @@
|
|||
|
||||
2D vector class
|
||||
|
||||
@maintainer Morgan McGuire, matrix@graphics3d.com
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2001-06-02
|
||||
@edited 2006-01-14
|
||||
Copyright 2000-2006, Morgan McGuire.
|
||||
@edited 2008-11-30
|
||||
|
||||
Copyright 2000-2009, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_VECTOR2_H
|
||||
#define G3D_VECTOR2_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "Vector2int16.h"
|
||||
#include <string>
|
||||
#include "G3D/Table.h"
|
||||
#include "G3D/HashTrait.h"
|
||||
#include "G3D/Vector2int16.h"
|
||||
#include "G3D/Random.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
class Vector2;
|
||||
class Vector3;
|
||||
class Vector4;
|
||||
class Any;
|
||||
|
||||
/**
|
||||
Do not subclass-- this implementation makes assumptions about the
|
||||
|
|
@ -38,29 +44,42 @@ private:
|
|||
bool operator>=(const Vector2&) const;
|
||||
|
||||
public:
|
||||
// coordinates
|
||||
float x, y;
|
||||
float x;
|
||||
float y;
|
||||
|
||||
// construction
|
||||
/** \param any Must either Vector2(#, #) or Vector2 {x = #, y = #}*/
|
||||
Vector2(const Any& any);
|
||||
|
||||
/** Converts the Vector2 to an Any. */
|
||||
operator Any() const;
|
||||
|
||||
/** Creates the zero vector */
|
||||
Vector2();
|
||||
Vector2(class TextInput& t);
|
||||
Vector2(class BinaryInput& b);
|
||||
Vector2(float x, float y);
|
||||
Vector2(float coordinate[2]);
|
||||
Vector2(double coordinate[2]);
|
||||
Vector2(const Vector2& rkVector);
|
||||
Vector2(const class Vector2int16& v);
|
||||
Vector2(const Vector2& other);
|
||||
Vector2(const Vector2int16& other);
|
||||
|
||||
float& operator[] (int i);
|
||||
const float& operator[] (int i) const;
|
||||
operator float* ();
|
||||
operator const float* () const;
|
||||
void serialize(class BinaryOutput& b) const;
|
||||
void deserialize(class BinaryInput& b);
|
||||
|
||||
void serialize(class TextOutput& t) const;
|
||||
void deserialize(class TextInput& t);
|
||||
|
||||
float& operator[](int i);
|
||||
const float& operator[](int i) const;
|
||||
|
||||
// assignment and comparison
|
||||
Vector2& operator= (const Vector2& rkVector);
|
||||
bool operator== (const Vector2& rkVector) const;
|
||||
bool operator!= (const Vector2& rkVector) const;
|
||||
unsigned int hashCode() const;
|
||||
Vector2& operator=(const Vector2& other);
|
||||
bool operator==(const Vector2& other) const;
|
||||
bool operator!=(const Vector2& other) const;
|
||||
size_t hashCode() const;
|
||||
bool fuzzyEq(const Vector2& other) const;
|
||||
bool fuzzyNe(const Vector2& other) const;
|
||||
|
||||
/** Returns true if this vector has finite length */
|
||||
bool isFinite() const;
|
||||
|
||||
|
|
@ -71,14 +90,21 @@ public:
|
|||
bool isUnit() const;
|
||||
|
||||
// arithmetic operations
|
||||
Vector2 operator+ (const Vector2& rkVector) const;
|
||||
Vector2 operator- (const Vector2& rkVector) const;
|
||||
Vector2 operator* (float fScalar) const;
|
||||
Vector2 operator* (const Vector2& rkVector) const;
|
||||
Vector2 operator/ (const Vector2& rkVector) const;
|
||||
Vector2 operator/ (float fScalar) const;
|
||||
Vector2 operator- () const;
|
||||
Vector2 operator+(const Vector2& v) const;
|
||||
Vector2 operator-(const Vector2& v) const;
|
||||
Vector2 operator*(float s) const;
|
||||
|
||||
/** Array (pointwise) multiplication */
|
||||
Vector2 operator*(const Vector2& v) const;
|
||||
|
||||
/** Array division */
|
||||
Vector2 operator/(const Vector2& v) const;
|
||||
Vector2 operator/(float s) const;
|
||||
|
||||
/** Unary minus */
|
||||
Vector2 operator-() const;
|
||||
|
||||
/** x + y */
|
||||
inline float sum() const {
|
||||
return x + y;
|
||||
}
|
||||
|
|
@ -103,16 +129,21 @@ public:
|
|||
}
|
||||
|
||||
// arithmetic updates
|
||||
Vector2& operator+= (const Vector2& rkVector);
|
||||
Vector2& operator-= (const Vector2& rkVector);
|
||||
Vector2& operator*= (float fScalar);
|
||||
Vector2& operator/= (float fScalar);
|
||||
Vector2& operator*= (const Vector2& rkVector);
|
||||
Vector2& operator/= (const Vector2& rkVector);
|
||||
Vector2& operator+=(const Vector2&);
|
||||
Vector2& operator-=(const Vector2&);
|
||||
Vector2& operator*=(float);
|
||||
Vector2& operator/=(float);
|
||||
Vector2& operator*=(const Vector2&);
|
||||
Vector2& operator/=(const Vector2&);
|
||||
|
||||
// vector operations
|
||||
|
||||
/** */
|
||||
float length() const;
|
||||
|
||||
/** Returns a unit-length vector */
|
||||
Vector2 direction() const;
|
||||
|
||||
/**
|
||||
Potentially less accurate but faster than direction().
|
||||
Only works if System::hasSSE is true.
|
||||
|
|
@ -121,20 +152,25 @@ public:
|
|||
return direction();
|
||||
}
|
||||
|
||||
float squaredLength () const;
|
||||
float dot (const Vector2& rkVector) const;
|
||||
float unitize (float fTolerance = 1e-06);
|
||||
float squaredLength() const;
|
||||
float dot(const Vector2& s) const;
|
||||
|
||||
Vector2 min(const Vector2 &v) const;
|
||||
Vector2 max(const Vector2 &v) const;
|
||||
/**
|
||||
Make this vector have unit length and return the old length.
|
||||
If the vector length was less than tolerance, do not normalize.
|
||||
*/
|
||||
float unitize(float fTolerance = 1e-06);
|
||||
|
||||
// Random unit vector
|
||||
static Vector2 random();
|
||||
Vector2 min(const Vector2& v) const;
|
||||
Vector2 max(const Vector2& v) const;
|
||||
|
||||
/** Uniformly distributed random vector on the unit sphere */
|
||||
static Vector2 random(Random& r = Random::common());
|
||||
|
||||
// Special values.
|
||||
// Intentionally not inlined: see Matrix3::identity() for details.
|
||||
static const Vector2& zero();
|
||||
inline static const Vector2& one() { static const Vector2 v(1, 1); return v; }
|
||||
static const Vector2& one();
|
||||
static const Vector2& unitX();
|
||||
static const Vector2& unitY();
|
||||
static const Vector2& inf();
|
||||
|
|
@ -144,16 +180,6 @@ public:
|
|||
/** Largest representable vector */
|
||||
static const Vector2& maxFinite();
|
||||
|
||||
|
||||
|
||||
// Deprecated. See Matrix3::identity() for details.
|
||||
/** @deprecated Use Vector2::zero() */
|
||||
static const Vector2 ZERO;
|
||||
/** @deprecated Use Vector2::unitX() */
|
||||
static const Vector2 UNIT_S;
|
||||
/** @deprecated Use Vector2::unitY() */
|
||||
static const Vector2 UNIT_T;
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
// 2-char swizzles
|
||||
|
|
@ -208,11 +234,6 @@ inline Vector2 operator*(int s, const Vector2& v) {
|
|||
}
|
||||
|
||||
|
||||
inline unsigned int hashCode(const G3D::Vector2& v) {
|
||||
return v.hashCode();
|
||||
}
|
||||
|
||||
|
||||
inline Vector2::Vector2 () : x(0.0f), y(0.0f) {
|
||||
}
|
||||
|
||||
|
|
@ -254,15 +275,6 @@ inline const float& Vector2::operator[] (int i) const {
|
|||
}
|
||||
|
||||
|
||||
inline Vector2::operator float* () {
|
||||
return (float*)this;
|
||||
}
|
||||
|
||||
inline Vector2::operator const float* () const {
|
||||
return (float*)this;
|
||||
}
|
||||
|
||||
|
||||
inline Vector2& Vector2::operator= (const Vector2& rkVector) {
|
||||
x = rkVector.x;
|
||||
y = rkVector.y;
|
||||
|
|
@ -421,7 +433,15 @@ inline bool Vector2::isUnit() const {
|
|||
return squaredLength() == 1.0f;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace G3D
|
||||
|
||||
template <>
|
||||
struct HashTrait<G3D::Vector2> {
|
||||
static size_t hashCode(const G3D::Vector2& key) {
|
||||
return key.hashCode();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Intentionally outside namespace to avoid operator overloading confusion
|
||||
inline G3D::Vector2 operator*(double s, const G3D::Vector2& v) {
|
||||
|
|
@ -431,8 +451,4 @@ inline G3D::Vector2 operator*(int s, const G3D::Vector2& v) {
|
|||
return v * (float)s;
|
||||
}
|
||||
|
||||
|
||||
inline unsigned int hashCode(const G3D::Vector2& v);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,20 +0,0 @@
|
|||
/**
|
||||
@file Vector2.inl
|
||||
|
||||
@maintainer Morgan McGuire, matrix@graphics3d.com
|
||||
@cite Portions by Laura Wollstadt, graphics3d.com
|
||||
|
||||
@cite Portions based on Dave Eberly'x Magic Software Library
|
||||
at http://www.magic-software.com
|
||||
|
||||
|
||||
@created 2001-06-02
|
||||
@edited 2006-01-14
|
||||
|
||||
Copyright 2000-2006, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -15,17 +15,15 @@
|
|||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/HashTrait.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
\class Vector2int16
|
||||
A Vector2 that packs its fields into uint16s.
|
||||
*/
|
||||
#ifdef G3D_WIN32
|
||||
// Switch to tight alignment
|
||||
#pragma pack(push, 2)
|
||||
#endif
|
||||
|
||||
G3D_BEGIN_PACKED_CLASS(2)
|
||||
class Vector2int16 {
|
||||
private:
|
||||
// Hidden operators
|
||||
|
|
@ -41,6 +39,7 @@ public:
|
|||
Vector2int16() : x(0), y(0) {}
|
||||
Vector2int16(G3D::int16 _x, G3D::int16 _y) : x(_x), y(_y){}
|
||||
Vector2int16(const class Vector2& v);
|
||||
Vector2int16(class BinaryInput& bi);
|
||||
|
||||
inline G3D::int16& operator[] (int i) {
|
||||
debugAssert(((unsigned int)i) <= 1);
|
||||
|
|
@ -52,6 +51,51 @@ public:
|
|||
return ((G3D::int16*)this)[i];
|
||||
}
|
||||
|
||||
inline Vector2int16 operator+(const Vector2int16& other) const {
|
||||
return Vector2int16(x + other.x, y + other.y);
|
||||
}
|
||||
|
||||
inline Vector2int16 operator-(const Vector2int16& other) const {
|
||||
return Vector2int16(x - other.x, y - other.y);
|
||||
}
|
||||
|
||||
inline Vector2int16 operator*(const Vector2int16& other) const {
|
||||
return Vector2int16(x * other.x, y * other.y);
|
||||
}
|
||||
|
||||
inline Vector2int16 operator*(const int s) const {
|
||||
return Vector2int16(x * s, y * s);
|
||||
}
|
||||
|
||||
inline Vector2int16& operator+=(const Vector2int16& other) {
|
||||
x += other.x;
|
||||
y += other.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Shifts both x and y */
|
||||
inline Vector2int16 operator>>(const int s) const {
|
||||
return Vector2int16(x >> s, y >> s);
|
||||
}
|
||||
|
||||
/** Shifts both x and y */
|
||||
inline Vector2int16 operator<<(const int s) const {
|
||||
return Vector2int16(x << s, y << s);
|
||||
}
|
||||
|
||||
inline Vector2int16& operator-=(const Vector2int16& other) {
|
||||
x -= other.x;
|
||||
y -= other.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Vector2int16& operator*=(const Vector2int16& other) {
|
||||
x *= other.x;
|
||||
y *= other.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector2int16 clamp(const Vector2int16& lo, const Vector2int16& hi);
|
||||
|
||||
inline bool operator== (const Vector2int16& rkVector) const {
|
||||
return ((int32*)this)[0] == ((int32*)&rkVector)[0];
|
||||
|
|
@ -61,15 +105,23 @@ public:
|
|||
return ((int32*)this)[0] != ((int32*)&rkVector)[0];
|
||||
}
|
||||
|
||||
}
|
||||
#if defined(G3D_LINUX) || defined(G3D_OSX)
|
||||
__attribute((aligned(1)))
|
||||
#endif
|
||||
;
|
||||
Vector2int16 max(const Vector2int16& v) const {
|
||||
return Vector2int16(iMax(x, v.x), iMax(y, v.y));
|
||||
}
|
||||
|
||||
#ifdef G3D_WIN32
|
||||
#pragma pack(pop)
|
||||
#endif
|
||||
Vector2int16 min(const Vector2int16& v) const {
|
||||
return Vector2int16(iMin(x, v.x), iMin(y, v.y));
|
||||
}
|
||||
|
||||
void serialize(class BinaryOutput& bo) const;
|
||||
void deserialize(class BinaryInput& bi);
|
||||
}
|
||||
G3D_END_PACKED_CLASS(2)
|
||||
|
||||
}
|
||||
|
||||
template<> struct HashTrait<G3D::Vector2int16> {
|
||||
static size_t hashCode(const G3D::Vector2int16& key) { return static_cast<size_t>(key.x + ((int)key.y << 16)); }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue