mirror of
https://github.com/mangosfour/server.git
synced 2025-12-14 16:37:01 +00:00
Merge remote branch 'origin/master' into 335
This commit is contained in:
commit
ce553c9997
302 changed files with 59699 additions and 5576 deletions
1
NEWS
1
NEWS
|
|
@ -15,6 +15,7 @@ http://mangos.lighthouseapp.com/
|
|||
|
||||
Version 0.16
|
||||
* Under discussion.
|
||||
* G3DLite lib upgrade to G3DLite 8.0b4
|
||||
* OpenSSL lib upgrade to OpenSSL 1.0.0.
|
||||
* Sockets lib use dropped.
|
||||
* dotconfpp lib use dropped.
|
||||
|
|
|
|||
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>
|
||||
|
|
@ -411,6 +411,13 @@ ACE_Ini_ImpExp::import_config (const ACE_TCHAR* filename)
|
|||
if (!in)
|
||||
return -1;
|
||||
|
||||
// MaNGOS addition: Try read utf8 header and skip it if exist for support utf8 format file
|
||||
ACE_UINT32 utf8header = 0;
|
||||
fgets((char*)&utf8header, 4, in); // Try read header
|
||||
if (utf8header != ACE_UINT32(0x00BFBBEF)) // If not found
|
||||
fseek(in, 0, SEEK_SET); // Reset read position
|
||||
// MaNGOS addition - end
|
||||
|
||||
// @@ Make this a dynamic size!
|
||||
ACE_TCHAR buffer[4096];
|
||||
ACE_Configuration_Section_Key section;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
if (num > numAllocated) {
|
||||
// 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 ((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.
|
||||
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 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]
|
||||
@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 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);
|
||||
@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,13 +91,11 @@ 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 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 new coordinate frame for the camera */
|
||||
void setCoordinateFrame(const CoordinateFrame& c);
|
||||
|
||||
/**
|
||||
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);
|
||||
/** 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.
|
||||
|
||||
inline double getFieldOfView() const {
|
||||
return fieldOfView;
|
||||
}
|
||||
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;
|
||||
|
||||
/** 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,90 +237,98 @@ 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;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the GCamera space width of the viewport.
|
||||
Sets a new value for the near clipping plane
|
||||
Expects a negative value
|
||||
*/
|
||||
float getViewportWidth(
|
||||
const class Rect2D& viewport) const;
|
||||
inline void setNearPlaneZ(float z) {
|
||||
debugAssert(z < 0);
|
||||
m_nearPlaneZ = z;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the GCamera space height of the viewport.
|
||||
Returns the camera space width of the viewport at the near plane.
|
||||
*/
|
||||
float getViewportHeight(
|
||||
const class Rect2D& viewport) const;
|
||||
float viewportWidth(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.
|
||||
/**
|
||||
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]
|
||||
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.
|
||||
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.
|
||||
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;
|
||||
void frustum(const Rect2D& viewport, GCamera::Frustum& f) const;
|
||||
|
||||
GCamera::Frustum frustum(const Rect2D& viewport) const;
|
||||
GCamera::Frustum frustum(const Rect2D& viewport) const;
|
||||
|
||||
/** Read and Write camera parameters */
|
||||
void serialize(class BinaryOutput& bo) const;
|
||||
void deserialize(class BinaryInput& bi);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
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.
|
||||
|
|
@ -85,14 +105,15 @@ public:
|
|||
return (const float*)&elt[0][0];
|
||||
}
|
||||
|
||||
Vector3 getColumn (int iCol) const;
|
||||
Vector3 getRow (int iRow) const;
|
||||
Vector3 column(int c) const;
|
||||
const Vector3& row(int r) 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,9 +89,9 @@ 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);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
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;
|
||||
const class Plane* plane,
|
||||
int numPlanes,
|
||||
int32& cullingPlaneIndex,
|
||||
const uint32 testMask,
|
||||
uint32& childMask) const;
|
||||
|
||||
/**
|
||||
See AABox::culledBy
|
||||
*/
|
||||
bool culledBy(
|
||||
const Array<Plane>& plane,
|
||||
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,88 +1,274 @@
|
|||
/**
|
||||
@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();
|
||||
|
||||
|
|
@ -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
|
||||
|
|
|
|||
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