Initial commit: ROW Client source code
Game client codebase including: - CharacterActionControl: Character and creature management - GlobalScript: Network, items, skills, quests, utilities - RYLClient: Main client application with GUI and event handlers - Engine: 3D rendering engine (RYLGL) - MemoryManager: Custom memory allocation - Library: Third-party dependencies (DirectX, boost, etc.) - Tools: Development utilities 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
256
Engine/CrossM/CrossM.vcproj
Normal file
256
Engine/CrossM/CrossM.vcproj
Normal file
@@ -0,0 +1,256 @@
|
||||
<?xml version="1.0" encoding="ks_c_5601-1987"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.10"
|
||||
Name="CrossM"
|
||||
ProjectGUID="{540A7517-D29E-4835-8392-1922B8D53B7B}"
|
||||
Keyword="Win32Proj">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="../../Library/$(ConfigurationName)"
|
||||
IntermediateDirectory="../../Intermediate/$(ProjectName)/$(ConfigurationName)"
|
||||
ConfigurationType="4"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="./Include"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
|
||||
MinimalRebuild="TRUE"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="FALSE"
|
||||
DebugInformationFormat="4"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="$(OutDir)/CrossM.lib"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="../../Library/$(ConfigurationName)"
|
||||
IntermediateDirectory="../../Intermediate/$(ProjectName)/$(ConfigurationName)"
|
||||
ConfigurationType="4"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="./Include"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
|
||||
RuntimeLibrary="0"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="FALSE"
|
||||
DebugInformationFormat="3"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="$(OutDir)/CrossM.lib"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release_NoGD|Win32"
|
||||
OutputDirectory="../../Library/$(ConfigurationName)"
|
||||
IntermediateDirectory="../../Intermediate/$(ProjectName)/$(ConfigurationName)"
|
||||
ConfigurationType="4"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="./Include"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
|
||||
RuntimeLibrary="0"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="FALSE"
|
||||
DebugInformationFormat="3"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="$(OutDir)/CrossM.lib"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release_MY|Win32"
|
||||
OutputDirectory="../../Library/$(ConfigurationName)"
|
||||
IntermediateDirectory="../../Intermediate/$(ProjectName)/$(ConfigurationName)"
|
||||
ConfigurationType="4"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="./Include"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
|
||||
RuntimeLibrary="0"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="FALSE"
|
||||
DebugInformationFormat="3"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="$(OutDir)/CrossM.lib"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Debug_MY|Win32"
|
||||
OutputDirectory="../../Library/$(ConfigurationName)"
|
||||
IntermediateDirectory="../../Intermediate/$(ProjectName)/$(ConfigurationName)"
|
||||
ConfigurationType="4"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="./Include"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
|
||||
MinimalRebuild="TRUE"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="FALSE"
|
||||
DebugInformationFormat="4"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="$(OutDir)/CrossM.lib"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Math"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath=".\Include\MathConst.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\MathUtil.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Include\MathUtil.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Include\Vector3.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Scene"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath=".\Src\CollisionEllipsoidHelper.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Include\CollisionEllipsoidHelper.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\OctreeCollider.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Include\OctreeCollider.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath=".\ReadMe.txt">
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
193
Engine/CrossM/CrossM.vcxproj
Normal file
193
Engine/CrossM/CrossM.vcxproj
Normal file
@@ -0,0 +1,193 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug_MY|Win32">
|
||||
<Configuration>Debug_MY</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release_MY|Win32">
|
||||
<Configuration>Release_MY</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release_NoGD|Win32">
|
||||
<Configuration>Release_NoGD</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{540A7517-D29E-4835-8392-1922B8D53B7B}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug_MY|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release_MY|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release_NoGD|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug_MY|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release_MY|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release_NoGD|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../Library/$(Configuration)\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../Intermediate/$(ProjectName)/$(Configuration)\</IntDir>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../Library/$(Configuration)\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../Intermediate/$(ProjectName)/$(Configuration)\</IntDir>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release_NoGD|Win32'">../../Library/$(Configuration)\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release_NoGD|Win32'">../../Intermediate/$(ProjectName)/$(Configuration)\</IntDir>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release_MY|Win32'">../../Library/$(Configuration)\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release_MY|Win32'">../../Intermediate/$(ProjectName)/$(Configuration)\</IntDir>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug_MY|Win32'">../../Library/$(Configuration)\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug_MY|Win32'">../../Intermediate/$(ProjectName)/$(Configuration)\</IntDir>
|
||||
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug_MY|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug_MY|Win32'" />
|
||||
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug_MY|Win32'" />
|
||||
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
|
||||
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
|
||||
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release_MY|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release_MY|Win32'" />
|
||||
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release_MY|Win32'" />
|
||||
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release_NoGD|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release_NoGD|Win32'" />
|
||||
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release_NoGD|Win32'" />
|
||||
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
|
||||
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>./Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>true</MinimalRebuild>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Lib>
|
||||
<OutputFile>$(OutDir)CrossM.lib</OutputFile>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>./Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<OpenMPSupport>true</OpenMPSupport>
|
||||
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
|
||||
</ClCompile>
|
||||
<Lib>
|
||||
<OutputFile>$(OutDir)CrossM.lib</OutputFile>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release_NoGD|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>./Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Lib>
|
||||
<OutputFile>$(OutDir)CrossM.lib</OutputFile>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release_MY|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>./Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Lib>
|
||||
<OutputFile>$(OutDir)CrossM.lib</OutputFile>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug_MY|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>./Include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>true</MinimalRebuild>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Lib>
|
||||
<OutputFile>$(OutDir)CrossM.lib</OutputFile>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Include\MathConst.h" />
|
||||
<ClInclude Include="Include\MathUtil.h" />
|
||||
<ClInclude Include="Include\Vector3.h" />
|
||||
<ClInclude Include="Include\CollisionEllipsoidHelper.h" />
|
||||
<ClInclude Include="Include\OctreeCollider.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Src\MathUtil.cpp" />
|
||||
<ClCompile Include="Src\CollisionEllipsoidHelper.cpp" />
|
||||
<ClCompile Include="Src\OctreeCollider.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="ReadMe.txt" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
42
Engine/CrossM/CrossM.vcxproj.filters
Normal file
42
Engine/CrossM/CrossM.vcxproj.filters
Normal file
@@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Math">
|
||||
<UniqueIdentifier>{1d328367-6680-4a76-8582-a7986b1ef097}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Scene">
|
||||
<UniqueIdentifier>{a57a23b6-3e84-4fbe-86a4-66cbe049b94b}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Include\MathConst.h">
|
||||
<Filter>Math</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Include\MathUtil.h">
|
||||
<Filter>Math</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Include\Vector3.h">
|
||||
<Filter>Math</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Include\CollisionEllipsoidHelper.h">
|
||||
<Filter>Scene</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Include\OctreeCollider.h">
|
||||
<Filter>Scene</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Src\MathUtil.cpp">
|
||||
<Filter>Math</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Src\CollisionEllipsoidHelper.cpp">
|
||||
<Filter>Scene</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Src\OctreeCollider.cpp">
|
||||
<Filter>Scene</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="ReadMe.txt" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
36
Engine/CrossM/Include/CollisionEllipsoidHelper.h
Normal file
36
Engine/CrossM/Include/CollisionEllipsoidHelper.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include "./Vector3.h"
|
||||
|
||||
|
||||
namespace CrossM{
|
||||
namespace Scene{
|
||||
|
||||
class CCollisionEllipsoidHelper{
|
||||
|
||||
public:
|
||||
CCollisionEllipsoidHelper();
|
||||
~CCollisionEllipsoidHelper();
|
||||
|
||||
void SetEllipsoidRadius(const Math::VECTOR3& vRadius);
|
||||
void SetHeightBias(float f);
|
||||
|
||||
// height bias 가 세팅된 후, 위치 설정은 아래 둘 중 아무것으로나 할 수 있다
|
||||
void SetEllipsoidCenter(const Math::VECTOR3& vCenter);
|
||||
void SetPosition(const Math::VECTOR3& vPos);
|
||||
|
||||
const Math::VECTOR3& GetEllipsoidRadius();
|
||||
const Math::VECTOR3& GetEllipsoidCenter();
|
||||
Math::VECTOR3 GetPosition(); // client 에서 이용하는 실제 위치
|
||||
|
||||
|
||||
private:
|
||||
// 충돌 타원체의 중심과 반지름벡터
|
||||
Math::VECTOR3 m_vEllipoidCenter;
|
||||
Math::VECTOR3 m_vEllipsoidRaius;
|
||||
|
||||
// client 측에서 이용하는 충돌점의 실제 타원체 중심 기준 높이 bias값
|
||||
float m_fHeightBias;
|
||||
};
|
||||
|
||||
}}
|
||||
9
Engine/CrossM/Include/MathConst.h
Normal file
9
Engine/CrossM/Include/MathConst.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
namespace CrossM{
|
||||
namespace Math{
|
||||
|
||||
const float F_EPSILON = 1.0e-5f;
|
||||
const float F_PI = 3.1415926535f;
|
||||
|
||||
}}
|
||||
84
Engine/CrossM/Include/MathUtil.h
Normal file
84
Engine/CrossM/Include/MathUtil.h
Normal file
@@ -0,0 +1,84 @@
|
||||
#include "./MathConst.h"
|
||||
#include "./Vector3.h"
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace CrossM{
|
||||
namespace Math{
|
||||
|
||||
|
||||
inline bool IsEquivalent(const float f1, const float f2, const float fEpsilon = F_EPSILON)
|
||||
{
|
||||
float d = f1 - f2;
|
||||
return (d < fEpsilon && d > -fEpsilon);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
점 v 가 boxMin, boxMax 를 최소/최대 점으로 가지는 AABB 에 포함되는지 여부를 체크
|
||||
|
||||
포함될 경우 true, 그렇지 않을 경우 false 반환
|
||||
*/
|
||||
inline bool IsPointInAABB(const VECTOR3& vPoint, const VECTOR3& vAABBMin , const VECTOR3& vAABBMax)
|
||||
{
|
||||
if (vAABBMin.x <= vPoint.x && vPoint.x < vAABBMax.x &&
|
||||
vAABBMin.y <= vPoint.y && vPoint.y < vAABBMax.y &&
|
||||
vAABBMin.z <= vPoint.z && vPoint.z < vAABBMax.z)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
f1Min ~ f1Max 구간과 f2Min ~ f2Max 구간이 겹치는지 체크
|
||||
단, 반드시 f1Min <= f1Max, f2Min <= f2Max 여야 한다
|
||||
*/
|
||||
inline bool IsRangeOverlap(float f1Min, float f1Max, float f2Min, float f2Max)
|
||||
{
|
||||
if (f1Min <= f2Max && f2Min <= f1Max)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// 삼각형이 AABB 안에 완전히 포함되는지 여부를 확인
|
||||
bool IsTriangleInAabb(const VECTOR3& vAabbMin, const VECTOR3& vAabbMax, const VECTOR3& vTri0, const VECTOR3& vTri1, const VECTOR3& vTri2);
|
||||
|
||||
// AABB 와 삼각형의 intersection 테스트
|
||||
bool CheckAabbTriangleIntersection(const VECTOR3& vAabbMin, const VECTOR3& vAabbMax, const VECTOR3& vTri0, const VECTOR3& vTri1, const VECTOR3& vTri2);
|
||||
|
||||
// AABB 와 AABB 의 intersection 테스트
|
||||
bool CheckAabbAabbIntersection(const VECTOR3& vAabb1Min, const VECTOR3& vAabb1Max, const VECTOR3& vAabb2Min, const VECTOR3& vAabb2Max);
|
||||
|
||||
// 삼각형/Sweeping Sphere 테스트를 위한 파라미터 구조체
|
||||
struct TriangSweepingSphere
|
||||
{
|
||||
Math::VECTOR3 m_vTri0;
|
||||
Math::VECTOR3 m_vTri1;
|
||||
Math::VECTOR3 m_vTri2;
|
||||
|
||||
Math::VECTOR3 m_vSphereSweepStart;
|
||||
Math::VECTOR3 m_vSphereSweepPath;
|
||||
float m_fSphereRadius;
|
||||
};
|
||||
|
||||
// 삼각형과 sweeping sphere 의 충돌 테스트. 충돌일 경우 충돌이 일어난 지점도 반환한다
|
||||
bool CheckTriangleSweepingSphereCollision(float &fOutT, VECTOR3& vOutContactPoint, bool& bOutContactInsideTriangle, const TriangSweepingSphere& triAndSphere);
|
||||
|
||||
// 삼각형 내에 점이 포함되어있는지 확인
|
||||
bool IsPointInTriangle(const VECTOR3& vPoint, const VECTOR3& vTri0, const VECTOR3& vTri1, const VECTOR3& vTri2);
|
||||
|
||||
}}
|
||||
|
||||
|
||||
|
||||
// 임시용 vector3 계열간 컨버전 함수
|
||||
template<class _T>
|
||||
void ConvVector3(CrossM::Math::VECTOR3& v, const _T& vOld)
|
||||
{
|
||||
v.SetValue(vOld.x, vOld.y, vOld.z);
|
||||
}
|
||||
137
Engine/CrossM/Include/OctreeCollider.h
Normal file
137
Engine/CrossM/Include/OctreeCollider.h
Normal file
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
Collision detection + response 를 처리하는 클래스
|
||||
충돌 삼각형의 culling 은 octree 를 이용
|
||||
|
||||
collision detection 과 response 알고리즘은 Kasper Fauerby 의
|
||||
'Improved Collision detection and Response' 에 기초하는 코드이다
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "./Vector3.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
// forward decl.
|
||||
struct IDirect3DDevice8;
|
||||
|
||||
|
||||
namespace CrossM{
|
||||
namespace Scene{
|
||||
|
||||
struct CollisionTriangleInfo
|
||||
{
|
||||
Math::VECTOR3 m_avVertex[3];
|
||||
// 부가적 정보..이를테면 이 삼각형이 속한 오브젝트의 id 라던가. 그런것이 필요할듯
|
||||
// 오브젝트 클래스(지형/하우스/오브젝트)+한 클래스 내에서의 오브젝트ID(각 하우스별 고유번호)
|
||||
// 같은 식의 자료형이 될지도?
|
||||
|
||||
Math::VECTOR3 m_vFaceNormal;
|
||||
};
|
||||
|
||||
// octree 의 node. 리프 노드뿐 아니라 줄기 노드도 삼각형의 인덱스를 가질 수 있다.
|
||||
// 바운딩 박스 내에 삼각형의 세 점이 완전히 포함되는 삼각형만 그 노드의 삼각형 인덱스 리스트에 기록된다.
|
||||
// (경계에 걸치는 그 삼각형의 세 점을 다 포함하는 상위 노드에 기록됨)
|
||||
class COctreeCollisionNode
|
||||
{
|
||||
public:
|
||||
COctreeCollisionNode();
|
||||
~COctreeCollisionNode();
|
||||
|
||||
// 현 노드의 하위 노드들을 재귀적으로 모두 해제
|
||||
void ReleaseSubNode();
|
||||
|
||||
// leaf node 인지 체크
|
||||
bool IsLeafNode();
|
||||
|
||||
// 자식 노드들을 생성하고, 자신의 노드에 포함된 삼각형의 인덱스들을 자식 노드로 분산시킨다.
|
||||
// 자기 자신의 노드에는 바운딩박스 값이 세팅된 상태여야 한다.
|
||||
void BuildSubNode(
|
||||
const std::vector< CollisionTriangleInfo >& vecTriangle,
|
||||
const size_t nMaximumRecursion, const size_t nMinPolyCount,
|
||||
size_t nCurrentRecursionLevel);
|
||||
|
||||
|
||||
// 충돌 객체의 swept volume 에 걸리는 충돌 노드들의 리스트를 vecCollidableNode 에 저장
|
||||
void CollectCollidableNodes(
|
||||
const Math::VECTOR3& vSweptVolumeMin, const Math::VECTOR3& vSweptVolumeMax,
|
||||
std::vector< COctreeCollisionNode* >& vecCollidableNode);
|
||||
|
||||
Math::VECTOR3 m_vBoundingMin;
|
||||
Math::VECTOR3 m_vBoundingMax;
|
||||
std::vector< size_t > m_vecTriangleIndex;
|
||||
|
||||
COctreeCollisionNode* m_apSubNode[8];
|
||||
};
|
||||
|
||||
|
||||
class COctreeCollider
|
||||
{
|
||||
public:
|
||||
COctreeCollider();
|
||||
~COctreeCollider();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Octree Build 관련 메소드
|
||||
|
||||
/*
|
||||
충돌 삼각형 갯수를 설정.
|
||||
충돌 삼각형이 내부적으로 저장될 공간이 할당되고, octree 정보가 파괴된다.
|
||||
BuildOctree() 가 호출되기 전까지 COctreeCollider 는 정상작동하지 않는다
|
||||
*/
|
||||
void SetTriangleCount(unsigned int uiTriangleCount);
|
||||
|
||||
/*
|
||||
삼각형 데이터 저장소의 포인터를 반환.
|
||||
이 메소드를 호출하면 삼각형 데이터가 변형된것으로 간주, octree 정보가 파괴된다.
|
||||
BuildOctree() 가 호출되기 전까지 COctreeCollider 는 정상작동하지 않는다
|
||||
*/
|
||||
void GetTriangleDataPtr(CollisionTriangleInfo*& pTriangleData);
|
||||
|
||||
// 세팅된 삼각형 정보를 기초로 octree 정보를 구축
|
||||
bool BuildOctree(const size_t nMaximumRecursion, const size_t nMinPolyCount);
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 충돌검출 및 반응 메소드
|
||||
|
||||
/*
|
||||
주어진 타원체의 이전 위치(prevPos)와 이동할 위치(nextPos) 를 파라미터로 넘기면,
|
||||
충돌을 체크하고 충돌이 일어났을 경우 적절한 위치로 수정된 이동 위치를 반환한다.
|
||||
*/
|
||||
void GetCollisionRespondingPosition(
|
||||
Math::VECTOR3& vRespondingPos,
|
||||
const Math::VECTOR3& vPrevPos, const Math::VECTOR3& vNewPos,
|
||||
const Math::VECTOR3& vEllipsoidRadius,
|
||||
const unsigned int nRecursionLevel = 1);
|
||||
|
||||
|
||||
// 테스트용 메소드, 충돌이 일어날 수 있는것으로 확인된 노드의 삼각형들을 렌더
|
||||
void RenderCollidableNodeTriangles(IDirect3DDevice8* pDevice);
|
||||
|
||||
|
||||
private:
|
||||
std::vector< CollisionTriangleInfo > m_vecCollisionTriangle;
|
||||
|
||||
Math::VECTOR3 m_vCollisionBoundingMin;
|
||||
Math::VECTOR3 m_vCollisionBoundingMax;
|
||||
|
||||
COctreeCollisionNode m_octreeRootNode;
|
||||
|
||||
|
||||
// 임시용, 충돌이 일어날 수 있는것으로 확인된 leaf 노드들
|
||||
std::vector< COctreeCollisionNode* > m_vecpCollidableNode;
|
||||
|
||||
// 임시용, 렌더용 버텍스 데이터
|
||||
std::vector< Math::VECTOR3 > m_vecRenderVertex;
|
||||
|
||||
// 임시용. 충돌이 일어난 삼각형의 인덱스
|
||||
size_t m_nColTriIndex;
|
||||
|
||||
};
|
||||
|
||||
|
||||
}}
|
||||
216
Engine/CrossM/Include/Vector3.h
Normal file
216
Engine/CrossM/Include/Vector3.h
Normal file
@@ -0,0 +1,216 @@
|
||||
#pragma once
|
||||
|
||||
#include "./MathConst.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
namespace CrossM{
|
||||
namespace Math{
|
||||
|
||||
struct VECTOR3
|
||||
{
|
||||
VECTOR3() {}
|
||||
~VECTOR3() {}
|
||||
|
||||
VECTOR3(const float _x, const float _y, const float _z) : x(_x), y(_y), z(_z) {}
|
||||
|
||||
VECTOR3(const VECTOR3& v) : x(v.x), y(v.y), z(v.z) {}
|
||||
|
||||
void SetValue(const float _x, const float _y, const float _z)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
z = _z;
|
||||
}
|
||||
|
||||
float x, y, z;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline VECTOR3& SetZeroVector(VECTOR3& v)
|
||||
{
|
||||
v.x = v.y = v.z = 0.0f;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
// 벡터에 값을 설정
|
||||
inline VECTOR3& SetValue(VECTOR3& vOut, const float x, const float y, const float z)
|
||||
{
|
||||
vOut.x = x;
|
||||
vOut.y = y;
|
||||
vOut.z = z;
|
||||
|
||||
return vOut;
|
||||
}
|
||||
|
||||
// 벡터 길이를 구함
|
||||
inline float GetLength(const VECTOR3& v)
|
||||
{
|
||||
return sqrtf(v.x*v.x + v.y*v.y + v.z*v.z);
|
||||
}
|
||||
|
||||
// 벡터 길이의 제곱을 구함
|
||||
inline float GetSquaredLength(const VECTOR3& v)
|
||||
{
|
||||
return v.x*v.x + v.y*v.y + v.z*v.z;
|
||||
}
|
||||
|
||||
// Normalize
|
||||
inline VECTOR3& Normalize(VECTOR3& vOut, const VECTOR3& vIn)
|
||||
{
|
||||
float fLen = GetLength(vIn);
|
||||
if (fLen < F_EPSILON)
|
||||
{
|
||||
// 벡터의 길이가 0에 가까울 경우 법선벡터는 x축방향벡터
|
||||
SetValue(vOut, 1.0f, 0.0f, 0.0f);
|
||||
return vOut;
|
||||
}
|
||||
|
||||
float fInv = 1.0f / fLen;
|
||||
vOut.x = vIn.x * fInv;
|
||||
vOut.y = vIn.y * fInv;
|
||||
vOut.z = vIn.z * fInv;
|
||||
|
||||
return vOut;
|
||||
}
|
||||
|
||||
// vOut = -vIn;
|
||||
inline VECTOR3& Negate(VECTOR3& vOut, const VECTOR3& vIn)
|
||||
{
|
||||
vOut.x = -vIn.x;
|
||||
vOut.y = -vIn.y;
|
||||
vOut.z = -vIn.z;
|
||||
|
||||
return vOut;
|
||||
}
|
||||
|
||||
// vOut = fScale x vIn
|
||||
inline VECTOR3& Scale(VECTOR3& vOut, const VECTOR3& vIn, const float fScale)
|
||||
{
|
||||
vOut.x = vIn.x * fScale;
|
||||
vOut.y = vIn.y * fScale;
|
||||
vOut.z = vIn.z * fScale;
|
||||
|
||||
return vOut;
|
||||
}
|
||||
|
||||
// vOut = v1 + v2
|
||||
inline VECTOR3& Add(VECTOR3& vOut, const VECTOR3& v1, const VECTOR3& v2)
|
||||
{
|
||||
vOut.x = v1.x + v2.x;
|
||||
vOut.y = v1.y + v2.y;
|
||||
vOut.z = v1.z + v2.z;
|
||||
|
||||
return vOut;
|
||||
}
|
||||
|
||||
// vOut = v1 - v2
|
||||
inline VECTOR3& Subtract(VECTOR3& vOut, const VECTOR3& v1, const VECTOR3& v2)
|
||||
{
|
||||
vOut.x = v1.x - v2.x;
|
||||
vOut.y = v1.y - v2.y;
|
||||
vOut.z = v1.z - v2.z;
|
||||
|
||||
return vOut;
|
||||
}
|
||||
|
||||
// v1 과 v2 의 내적.
|
||||
inline float DotProduct(const VECTOR3& v1, const VECTOR3& v2)
|
||||
{
|
||||
return v1.x*v2.x + v1.y*v2.y + v1.z*v2.z;
|
||||
}
|
||||
|
||||
// v1 과 v2 의 외적. vOut = v1 x v2
|
||||
inline VECTOR3& CrossProduct(VECTOR3& vOut, const VECTOR3& v1, const VECTOR3& v2)
|
||||
{
|
||||
VECTOR3 vTmp; // vOut 이 v1 이나 v2 와 같을 경우 연산 문제를 방지하기 위한 임시변수
|
||||
|
||||
vTmp.x = v1.y*v2.z - v1.z*v2.y;
|
||||
vTmp.y = v1.z*v2.x - v1.x*v2.z;
|
||||
vTmp.z = v1.x*v2.y - v1.y*v2.x;
|
||||
|
||||
vOut = vTmp;
|
||||
|
||||
return vOut;
|
||||
}
|
||||
|
||||
// v1 에서 v2 로 비율 f만큼 선형으로 변화한 벡터를 구함(선형보간)
|
||||
inline VECTOR3& Lerp(VECTOR3& vOut, const VECTOR3& v1, const VECTOR3& v2, const float f)
|
||||
{
|
||||
float fRem = 1.0f - f;
|
||||
vOut.x = v1.x*fRem + v2.x*f;
|
||||
vOut.y = v1.y*fRem + v2.y*f;
|
||||
vOut.z = v1.z*fRem + v2.z*f;
|
||||
|
||||
return vOut;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// 단항 - 연산자
|
||||
inline VECTOR3 operator - (const VECTOR3& v)
|
||||
{
|
||||
VECTOR3 vRet;
|
||||
|
||||
return Negate(vRet, v);
|
||||
}
|
||||
|
||||
// 벡터합
|
||||
inline VECTOR3 operator + (const VECTOR3& v1, const VECTOR3& v2)
|
||||
{
|
||||
VECTOR3 vRet;
|
||||
|
||||
return Add(vRet, v1, v2);
|
||||
}
|
||||
|
||||
// 벡터차
|
||||
inline VECTOR3 operator - (const VECTOR3& v1, const VECTOR3& v2)
|
||||
{
|
||||
VECTOR3 vRet;
|
||||
|
||||
return Subtract(vRet, v1, v2);
|
||||
}
|
||||
|
||||
// 벡터 스칼라배(상수먼저)
|
||||
inline VECTOR3 operator * (const float f, const VECTOR3& v)
|
||||
{
|
||||
VECTOR3 vRet;
|
||||
|
||||
return Scale(vRet, v, f);
|
||||
}
|
||||
|
||||
// 벡터 스칼라배(벡터먼저)
|
||||
inline VECTOR3 operator * (const VECTOR3& v, const float f)
|
||||
{
|
||||
VECTOR3 vRet;
|
||||
|
||||
return Scale(vRet, v, f);
|
||||
}
|
||||
|
||||
// 벡터 스칼라배(상수로 나눔)
|
||||
inline VECTOR3 operator / (const VECTOR3& v, const float& f)
|
||||
{
|
||||
VECTOR3 vRet;
|
||||
|
||||
return Scale(vRet, v, 1.0f/f);
|
||||
}
|
||||
|
||||
// 벡터 내적
|
||||
inline float operator * (const VECTOR3& v1, const VECTOR3& v2)
|
||||
{
|
||||
return DotProduct(v1, v2);
|
||||
}
|
||||
|
||||
// 벡터 외적
|
||||
inline VECTOR3 operator ^ (const VECTOR3& v1, const VECTOR3& v2)
|
||||
{
|
||||
VECTOR3 vRet;
|
||||
|
||||
return CrossProduct(vRet, v1, v2);
|
||||
}
|
||||
|
||||
|
||||
}}
|
||||
21
Engine/CrossM/ReadMe.txt
Normal file
21
Engine/CrossM/ReadMe.txt
Normal file
@@ -0,0 +1,21 @@
|
||||
========================================================================
|
||||
정적 라이브러리 : CrossM 프로젝트 개요
|
||||
========================================================================
|
||||
|
||||
응용 프로그램 마법사에서 이 CrossM 라이브러리 프로젝트를 만들었습니다.
|
||||
프로젝트에 대해 소스 파일은 만들어지지 않았습니다.
|
||||
|
||||
|
||||
CrossM.vcproj
|
||||
응용 프로그램 마법사를 사용하여 생성한 VC++ 프로젝트의 기본 프로젝트 파일입니다.
|
||||
해당 파일을 생성한 Visual C++의 버전 정보를 비롯하여
|
||||
응용 프로그램 마법사에서 선택한 플랫폼, 구성 및
|
||||
프로젝트 기능에 대한 정보가 들어 있습니다.
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
기타 참고:
|
||||
|
||||
응용 프로그램 마법사에서 사용하는 "TODO:" 주석은 사용자가 추가하거나 사용자 지정해야 하는
|
||||
소스 코드 부분을 나타냅니다.
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
56
Engine/CrossM/Src/CollisionEllipsoidHelper.cpp
Normal file
56
Engine/CrossM/Src/CollisionEllipsoidHelper.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
#include "../Include/CollisionEllipsoidHelper.h"
|
||||
|
||||
|
||||
namespace CrossM{
|
||||
namespace Scene{
|
||||
|
||||
CCollisionEllipsoidHelper::CCollisionEllipsoidHelper()
|
||||
{
|
||||
m_vEllipoidCenter.SetValue(0,0,0);
|
||||
m_vEllipsoidRaius.SetValue(1,1,1);
|
||||
|
||||
m_fHeightBias = 0.0f;
|
||||
}
|
||||
|
||||
CCollisionEllipsoidHelper::~CCollisionEllipsoidHelper()
|
||||
{
|
||||
}
|
||||
|
||||
void CCollisionEllipsoidHelper::SetEllipsoidRadius(const Math::VECTOR3& vRadius)
|
||||
{
|
||||
m_vEllipsoidRaius = vRadius;
|
||||
}
|
||||
|
||||
void CCollisionEllipsoidHelper::SetHeightBias(float f)
|
||||
{
|
||||
m_fHeightBias = f;
|
||||
}
|
||||
|
||||
void CCollisionEllipsoidHelper::SetEllipsoidCenter(const Math::VECTOR3& vCenter)
|
||||
{
|
||||
m_vEllipoidCenter = vCenter;
|
||||
}
|
||||
|
||||
void CCollisionEllipsoidHelper::SetPosition(const Math::VECTOR3& vPos)
|
||||
{
|
||||
m_vEllipoidCenter.SetValue(vPos.x, vPos.y-m_fHeightBias, vPos.z);
|
||||
}
|
||||
|
||||
const Math::VECTOR3& CCollisionEllipsoidHelper::GetEllipsoidRadius()
|
||||
{
|
||||
return m_vEllipsoidRaius;
|
||||
}
|
||||
|
||||
const Math::VECTOR3& CCollisionEllipsoidHelper::GetEllipsoidCenter()
|
||||
{
|
||||
return m_vEllipoidCenter;
|
||||
}
|
||||
|
||||
|
||||
Math::VECTOR3 CCollisionEllipsoidHelper::GetPosition()
|
||||
{
|
||||
return Math::VECTOR3(m_vEllipoidCenter.x, m_vEllipoidCenter.y+m_fHeightBias, m_vEllipoidCenter.z);
|
||||
}
|
||||
|
||||
|
||||
}}
|
||||
419
Engine/CrossM/Src/MathUtil.cpp
Normal file
419
Engine/CrossM/Src/MathUtil.cpp
Normal file
@@ -0,0 +1,419 @@
|
||||
#include "../Include/MathUtil.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace CrossM{
|
||||
namespace Math{
|
||||
|
||||
|
||||
// 삼각형이 AABB 안에 완전히 포함되는지 검사
|
||||
bool IsTriangleInAabb(const VECTOR3& vAabbMin, const VECTOR3& vAabbMax, const VECTOR3& vTri0, const VECTOR3& vTri1, const VECTOR3& vTri2)
|
||||
{
|
||||
if (vAabbMin.x <= vTri0.x && vTri0.x <= vAabbMax.x &&
|
||||
vAabbMin.y <= vTri0.y && vTri0.y <= vAabbMax.y &&
|
||||
vAabbMin.z <= vTri0.z && vTri0.z <= vAabbMax.z &&
|
||||
vAabbMin.x <= vTri1.x && vTri1.x <= vAabbMax.x &&
|
||||
vAabbMin.y <= vTri1.y && vTri1.y <= vAabbMax.y &&
|
||||
vAabbMin.z <= vTri1.z && vTri1.z <= vAabbMax.z &&
|
||||
vAabbMin.x <= vTri2.x && vTri2.x <= vAabbMax.x &&
|
||||
vAabbMin.y <= vTri2.y && vTri2.y <= vAabbMax.y &&
|
||||
vAabbMin.z <= vTri2.z && vTri2.z <= vAabbMax.z)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// 삼각형과 AABB 가 만나는지를 검사
|
||||
bool CheckAabbTriangleIntersection(const VECTOR3& vAabbMin, const VECTOR3& vAabbMax, const VECTOR3& vTri0, const VECTOR3& vTri1, const VECTOR3& vTri2)
|
||||
{
|
||||
// Separation of Axes 에 따른 AABB - triangle intersection test 구현
|
||||
|
||||
// 6 축에 대해 AABB 와 삼각형을 projection 한 뒤, 둘이 겹치는지 여부를 확인한다
|
||||
// 모든 축에 대해 겹치면 둘은 만나는것이고, 한 축에 대해서라도 겹치지 않는다면 만나지 않는 것이다
|
||||
|
||||
float fBoxProjectionMin, fBoxProjectionMax;
|
||||
float fTriProjectionMin, fTriProjectionMax;
|
||||
|
||||
// AABB 의 세 축에 대한 projection 을 검사
|
||||
|
||||
// X 축
|
||||
fBoxProjectionMin = vAabbMin.x;
|
||||
fBoxProjectionMax = vAabbMax.x;
|
||||
fTriProjectionMin = std::min(vTri0.x, std::min(vTri1.x, vTri2.x));
|
||||
fTriProjectionMax = std::max(vTri0.x, std::max(vTri1.x, vTri2.x));
|
||||
if (false == IsRangeOverlap(fTriProjectionMin, fTriProjectionMax, fBoxProjectionMin, fBoxProjectionMax))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Y 축
|
||||
fBoxProjectionMin = vAabbMin.y;
|
||||
fBoxProjectionMax = vAabbMax.y;
|
||||
fTriProjectionMin = std::min(vTri0.y, std::min(vTri1.y, vTri2.y));
|
||||
fTriProjectionMax = std::max(vTri0.y, std::max(vTri1.y, vTri2.y));
|
||||
if (false == IsRangeOverlap(fTriProjectionMin, fTriProjectionMax, fBoxProjectionMin, fBoxProjectionMax))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Z 축
|
||||
fBoxProjectionMin = vAabbMin.z;
|
||||
fBoxProjectionMax = vAabbMax.z;
|
||||
fTriProjectionMin = std::min(vTri0.z, std::min(vTri1.z, vTri2.z));
|
||||
fTriProjectionMax = std::max(vTri0.z, std::max(vTri1.z, vTri2.z));
|
||||
if (false == IsRangeOverlap(fTriProjectionMin, fTriProjectionMax, fBoxProjectionMin, fBoxProjectionMax))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// 삼각형의 의 세 축에 대한 projection 을 검사
|
||||
VECTOR3 avAxis[3]; // 삼각형의 세 모서리
|
||||
Math::Subtract(avAxis[0], vTri1, vTri0);
|
||||
Math::Subtract(avAxis[1], vTri2, vTri0);
|
||||
Math::Subtract(avAxis[2], vTri2, vTri1);
|
||||
|
||||
// 삼각형 각 점을 축에 projection 한 값
|
||||
float fProjectionTri0, fProjectionTri1, fProjectionTri2;
|
||||
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
VECTOR3& vAxis = avAxis[i];
|
||||
|
||||
// AABB 의 max/min 점의 xyz 는 각각의 최대/최소값이므로,
|
||||
// axis 의 각 컴포넌트와 내적했을때 최대값을 구하려면
|
||||
// x,y,z 각각의 곱이 큰 쪽 끼리 골라서 더하면 된다.
|
||||
// (어차피 AABB 여덟점이 xyz 각각의 최대/최소간의 조합이므로,
|
||||
// x,y,z 를 각각 임의로 최대/최소를 선택한다 해도 어뎗 점 안에 모두 포함되는 조합이다.)
|
||||
|
||||
fBoxProjectionMin =
|
||||
((vAxis.x > 0) ? vAabbMin.x : vAabbMax.x) * vAxis.x +
|
||||
((vAxis.y > 0) ? vAabbMin.y : vAabbMax.y) * vAxis.y +
|
||||
((vAxis.z > 0) ? vAabbMin.z : vAabbMax.z) * vAxis.z;
|
||||
|
||||
fBoxProjectionMax =
|
||||
((vAxis.x > 0) ? vAabbMax.x : vAabbMin.x) * vAxis.x +
|
||||
((vAxis.y > 0) ? vAabbMax.y : vAabbMin.y) * vAxis.y +
|
||||
((vAxis.z > 0) ? vAabbMax.z : vAabbMin.z) * vAxis.z;
|
||||
|
||||
fProjectionTri0 = Math::DotProduct(vTri0, vAxis);
|
||||
fProjectionTri1 = Math::DotProduct(vTri1, vAxis);
|
||||
fProjectionTri2 = Math::DotProduct(vTri2, vAxis);
|
||||
|
||||
fTriProjectionMin = std::min(fProjectionTri0, std::min(fProjectionTri1, fProjectionTri2));
|
||||
fTriProjectionMax = std::max(fProjectionTri0, std::max(fProjectionTri1, fProjectionTri2));
|
||||
|
||||
if (false == IsRangeOverlap(fTriProjectionMin, fTriProjectionMax, fBoxProjectionMin, fBoxProjectionMax))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// 두 AABB 가 만나는지 검사
|
||||
bool CheckAabbAabbIntersection(const VECTOR3& vAabb1Min, const VECTOR3& vAabb1Max, const VECTOR3& vAabb2Min, const VECTOR3& vAabb2Max)
|
||||
{
|
||||
if (false ==IsRangeOverlap(vAabb1Min.x, vAabb1Max.x, vAabb2Min.x, vAabb2Max.x)) return false;
|
||||
if (false ==IsRangeOverlap(vAabb1Min.y, vAabb1Max.y, vAabb2Min.y, vAabb2Max.y)) return false;
|
||||
if (false ==IsRangeOverlap(vAabb1Min.z, vAabb1Max.z, vAabb2Min.z, vAabb2Max.z)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// CheckTriangleSweepingSphereCollision 의 부속 함수.
|
||||
// ax^2 + bx + c 의 해 중 min~max 범위 내의 가장 작은 해를 반환한다. 만족하는 해가 없으면 false 반환
|
||||
static bool GetLowestRootInRange(const float a, const float b, const float c, const float fMinRoot, const float fMaxRoot, float& fRoot)
|
||||
{
|
||||
// 실수해가 존재하는지 판별식 계산
|
||||
float fDeterminant = b*b - 4.0f*a*c;
|
||||
|
||||
// 실수해가 존재하지 않으면 해 없음
|
||||
if (fDeterminant < 0.0f) return false;
|
||||
|
||||
// 두개의 해를 계산한다
|
||||
float fSqrtD = sqrtf(fDeterminant);
|
||||
float r1 = (-b - fSqrtD) / (2*a);
|
||||
float r2 = (-b + fSqrtD) / (2*a);
|
||||
|
||||
// r1 < r2 의 크기가 되도록 정렬
|
||||
if (r1 > r2) std::swap(r1, r2);
|
||||
|
||||
// 작은쪽부터 범위 내인지 판별해, 범위내일경우 해로서 리턴
|
||||
if (r1 > fMinRoot && r1 < fMaxRoot)
|
||||
{
|
||||
fRoot = r1;
|
||||
return true;
|
||||
}
|
||||
|
||||
// 작은 해 쪽이 범위내에 들지 않으면, 큰 해 쪽이 범위내인지 검사한다
|
||||
if (r2 > fMinRoot && r2 < fMaxRoot)
|
||||
{
|
||||
fRoot = r2;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool CheckTriangleSweepingSphereCollision(float &fOutT, VECTOR3& vOutContactPoint, bool& bOutContactInsideTriangle, const TriangSweepingSphere& triAndSphere)
|
||||
{
|
||||
// 약간의 alias
|
||||
const Math::VECTOR3 &vBasePoint = triAndSphere.m_vSphereSweepStart;
|
||||
const Math::VECTOR3 &vTri0 = triAndSphere.m_vTri0;
|
||||
const Math::VECTOR3 &vTri1 = triAndSphere.m_vTri1;
|
||||
const Math::VECTOR3 &vTri2 = triAndSphere.m_vTri2;
|
||||
const Math::VECTOR3 &vPath = triAndSphere.m_vSphereSweepPath;
|
||||
|
||||
// 삼각형의 세 모서리
|
||||
Math::VECTOR3 vTriEdge01, vTriEdge02, vTriEdge12;
|
||||
|
||||
// 삼각형을 포함하는 평면. 추후 plane 클래스 등으로 만들어야 할 듯
|
||||
Math::VECTOR3 vTriPlaneNormal;
|
||||
float fTriPlaneConstant;
|
||||
|
||||
// 삼각형의 세 모서리 벡터를 구하고..
|
||||
Math::Subtract(vTriEdge01, vTri1, vTri0);
|
||||
Math::Subtract(vTriEdge02, vTri2, vTri0);
|
||||
Math::Subtract(vTriEdge12, vTri2, vTri1);
|
||||
|
||||
// 삼각형이 포함된 평면의 파라미터들을 구함
|
||||
Math::CrossProduct(vTriPlaneNormal, vTriEdge01, vTriEdge02);
|
||||
Math::Normalize(vTriPlaneNormal, vTriPlaneNormal);
|
||||
fTriPlaneConstant = -Math::DotProduct(vTriPlaneNormal, vTri0);
|
||||
|
||||
// sweeping path 와 충돌평면법선 내적
|
||||
float fNormalDotPath = Math::DotProduct(vTriPlaneNormal, vPath);
|
||||
|
||||
// sphere 의 진행방향이 같은 방향이면 체크안함
|
||||
if (fNormalDotPath > 0.0f)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
float t0, t1;
|
||||
bool bEmbededInPlane = false;
|
||||
|
||||
float fSignedDistBaseToTriPlane = Math::DotProduct(vTriPlaneNormal, vBasePoint) + fTriPlaneConstant;
|
||||
|
||||
if (0.0f == fNormalDotPath)
|
||||
{
|
||||
// sphere 가 삼각형면과 평행하게 진행
|
||||
|
||||
if (fabs(fSignedDistBaseToTriPlane) >= triAndSphere.m_fSphereRadius)
|
||||
{
|
||||
return false; // 삼각형면에서 멀리 떨어져서 평행이동중
|
||||
}
|
||||
else
|
||||
{
|
||||
bEmbededInPlane = true;
|
||||
t0 = 0.0f;
|
||||
t1 = 1.0f;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
t0 = (-triAndSphere.m_fSphereRadius-fSignedDistBaseToTriPlane)/fNormalDotPath;
|
||||
t1 = (triAndSphere.m_fSphereRadius-fSignedDistBaseToTriPlane)/fNormalDotPath;
|
||||
|
||||
// t0 < t1 으로 소트
|
||||
if (t0 > t1)
|
||||
{
|
||||
std::swap(t0, t1);
|
||||
}
|
||||
|
||||
// t 구간이 sphere 이동경로 선분 내에 있지 않다
|
||||
if (t0 > 1.0f || t1 <0.0f)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// t 값을 0~1 구간내로 클램핑
|
||||
t0 = std::max(t0, 0.0f);
|
||||
t1 = std::min(t1, 1.0f);
|
||||
}
|
||||
|
||||
VECTOR3 vContactPoint;
|
||||
bool bFoundCollision = false;
|
||||
float t = 1.0f;
|
||||
|
||||
// 삼각형 내부와 체크
|
||||
if (!bEmbededInPlane)
|
||||
{
|
||||
vContactPoint = vBasePoint + (vPath*t0) - vTriPlaneNormal;
|
||||
|
||||
if (IsPointInTriangle(vContactPoint, vTri0, vTri1, vTri2))
|
||||
{
|
||||
bFoundCollision = true;
|
||||
t = t0;
|
||||
}
|
||||
}
|
||||
|
||||
// 아직 충돌점을 찾지 못했다면 모서리와 꼭지점에 대해 테스트를 해야한다
|
||||
if (!bFoundCollision)
|
||||
{
|
||||
float fSQuaredPathLength = GetSquaredLength(vPath);
|
||||
float a, b, c;
|
||||
float newT;
|
||||
float fSquaredRadius = triAndSphere.m_fSphereRadius*triAndSphere.m_fSphereRadius;
|
||||
|
||||
a = fSQuaredPathLength;
|
||||
|
||||
// vTri0
|
||||
b = 2.0f * (DotProduct(vPath, vBasePoint - vTri0));
|
||||
c = (Math::GetSquaredLength(vTri0 - vBasePoint) - fSquaredRadius);
|
||||
if (GetLowestRootInRange(a, b, c, 0.0f, t, newT))
|
||||
{
|
||||
t = newT;
|
||||
bFoundCollision = true;
|
||||
vContactPoint = vTri0;
|
||||
}
|
||||
|
||||
// vTri1
|
||||
if (bFoundCollision)
|
||||
{
|
||||
b = 2.0f * (DotProduct(vPath, vBasePoint - vTri1));
|
||||
c = (Math::GetSquaredLength(vTri1 - vBasePoint) - fSquaredRadius);
|
||||
if (GetLowestRootInRange(a, b, c, 0.0f, t, newT))
|
||||
{
|
||||
t = newT;
|
||||
bFoundCollision = true;
|
||||
vContactPoint = vTri1;
|
||||
}
|
||||
}
|
||||
|
||||
// vTri2
|
||||
if (bFoundCollision)
|
||||
{
|
||||
b = 2.0f * (DotProduct(vPath, vBasePoint - vTri2));
|
||||
c = (Math::GetSquaredLength(vTri2 - vBasePoint) - fSquaredRadius);
|
||||
if (GetLowestRootInRange(a, b, c, 0.0f, t, newT))
|
||||
{
|
||||
t = newT;
|
||||
bFoundCollision = true;
|
||||
vContactPoint = vTri0;
|
||||
}
|
||||
}
|
||||
|
||||
// 모서리에 대해 테스트
|
||||
VECTOR3 vBaseToVertex;
|
||||
float fEdgeSquaredLength;
|
||||
float fEdgeDotPath;
|
||||
float fEdgeDotBaseToVertex;
|
||||
|
||||
// vTri0 ~ vTri1
|
||||
vBaseToVertex = vTri0 - vBasePoint;
|
||||
fEdgeSquaredLength = GetSquaredLength(vTriEdge01);
|
||||
fEdgeDotPath = DotProduct(vTriEdge01, vPath);
|
||||
fEdgeDotBaseToVertex = DotProduct(vTriEdge01, vBaseToVertex);
|
||||
|
||||
a = fEdgeSquaredLength* -fSQuaredPathLength +
|
||||
fEdgeDotPath*fEdgeDotPath;
|
||||
b = fEdgeSquaredLength* (2.0f*Math::DotProduct(vPath, vBaseToVertex)) -
|
||||
2.0f*fEdgeDotPath*fEdgeDotBaseToVertex;
|
||||
c = (fEdgeSquaredLength* (1.0f - Math::GetSquaredLength(vBaseToVertex)) +
|
||||
fEdgeDotBaseToVertex*fEdgeDotBaseToVertex);
|
||||
|
||||
if (GetLowestRootInRange(a, b, c, 0.0f, t, newT))
|
||||
{
|
||||
float f = (fEdgeDotPath*t - fEdgeDotBaseToVertex) / fEdgeSquaredLength;
|
||||
if (f >= 0.0f && f <= 1.0f)
|
||||
{
|
||||
t = newT;
|
||||
bFoundCollision = true;
|
||||
vContactPoint = vTri0 + vTriEdge01*f;
|
||||
}
|
||||
}
|
||||
|
||||
// vTri0 ~ vTri2
|
||||
vBaseToVertex = vTri0 - vBasePoint;
|
||||
fEdgeSquaredLength = GetSquaredLength(vTriEdge02);
|
||||
fEdgeDotPath = DotProduct(vTriEdge02, vPath);
|
||||
fEdgeDotBaseToVertex = DotProduct(vTriEdge02, vBaseToVertex);
|
||||
|
||||
a = fEdgeSquaredLength* -fSQuaredPathLength +
|
||||
fEdgeDotPath*fEdgeDotPath;
|
||||
b = fEdgeSquaredLength* (2.0f*Math::DotProduct(vPath, vBaseToVertex)) -
|
||||
2.0f*fEdgeDotPath*fEdgeDotBaseToVertex;
|
||||
c = (fEdgeSquaredLength* (1.0f - Math::GetSquaredLength(vBaseToVertex)) +
|
||||
fEdgeDotBaseToVertex*fEdgeDotBaseToVertex);
|
||||
|
||||
if (GetLowestRootInRange(a, b, c, 0.0f, t, newT))
|
||||
{
|
||||
float f = (fEdgeDotPath*t - fEdgeDotBaseToVertex) / fEdgeSquaredLength;
|
||||
if (f >= 0.0f && f <= 1.0f)
|
||||
{
|
||||
t = newT;
|
||||
bFoundCollision = true;
|
||||
vContactPoint = vTri0 + vTriEdge02*f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// vTri1 ~ vTri2
|
||||
vBaseToVertex = vTri1 - vBasePoint;
|
||||
fEdgeSquaredLength = GetSquaredLength(vTriEdge12);
|
||||
fEdgeDotPath = DotProduct(vTriEdge12, vPath);
|
||||
fEdgeDotBaseToVertex = DotProduct(vTriEdge12, vBaseToVertex);
|
||||
|
||||
a = fEdgeSquaredLength* -fSQuaredPathLength +
|
||||
fEdgeDotPath*fEdgeDotPath;
|
||||
b = fEdgeSquaredLength* (2.0f*Math::DotProduct(vPath, vBaseToVertex)) -
|
||||
2.0f*fEdgeDotPath*fEdgeDotBaseToVertex;
|
||||
c = (fEdgeSquaredLength* (1.0f - Math::GetSquaredLength(vBaseToVertex)) +
|
||||
fEdgeDotBaseToVertex*fEdgeDotBaseToVertex);
|
||||
|
||||
if (GetLowestRootInRange(a, b, c, 0.0f, t, newT))
|
||||
{
|
||||
float f = (fEdgeDotPath*t - fEdgeDotBaseToVertex) / fEdgeSquaredLength;
|
||||
if (f >= 0.0f && f <= 1.0f)
|
||||
{
|
||||
t = newT;
|
||||
bFoundCollision = true;
|
||||
vContactPoint = vTri1 + vTriEdge12*f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bFoundCollision)
|
||||
{
|
||||
fOutT = t;
|
||||
vOutContactPoint = vContactPoint;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// 지정된 점이 삼각형 내에 포함되는지 확인하는 코드
|
||||
// Fauerby 의 글에 Keidy 라는 사람이 기고한 가장 빠른 루틴이라고 한다
|
||||
// 수학적인 증명은.. 모르겠다-_- 일단 이용
|
||||
bool IsPointInTriangle(const VECTOR3& p, const VECTOR3& vTri0, const VECTOR3& vTri1, const VECTOR3& vTri2)
|
||||
{
|
||||
// 원점을 낀 두 삼각형 모서리, 원점을 기준으로 한 p 의 위치벡터
|
||||
VECTOR3 vEdge1, vEdge2, pTri;
|
||||
|
||||
Math::Subtract(vEdge1, vTri1, vTri0);
|
||||
Math::Subtract(vEdge2, vTri2, vTri0);
|
||||
Math::Subtract(pTri, p, vTri0);
|
||||
|
||||
float a = Math::DotProduct(vEdge1, vEdge1);
|
||||
float b = Math::DotProduct(vEdge1, vEdge2);
|
||||
float c = Math::DotProduct(vEdge2, vEdge2);
|
||||
float d = Math::DotProduct(pTri, vEdge1);
|
||||
float e = Math::DotProduct(pTri, vEdge2);
|
||||
|
||||
float x = d*c - e*b;
|
||||
float y = e*a - d*b;
|
||||
float z = x + y - (a*c - b*b);
|
||||
|
||||
return ( ((unsigned int&)z) & ~ ( ((unsigned int&)x) | ((unsigned int&)y) ) & 0x80000000) != 0 ? true : false;
|
||||
}
|
||||
|
||||
|
||||
}}
|
||||
541
Engine/CrossM/Src/OctreeCollider.cpp
Normal file
541
Engine/CrossM/Src/OctreeCollider.cpp
Normal file
@@ -0,0 +1,541 @@
|
||||
#include "../Include/OctreeCollider.h"
|
||||
#include "../Include/MathUtil.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
|
||||
#include <windows.h>
|
||||
#include <d3d8.h>
|
||||
#include <d3dx8.h>
|
||||
|
||||
|
||||
namespace CrossM{
|
||||
namespace Scene{
|
||||
|
||||
|
||||
|
||||
COctreeCollisionNode::COctreeCollisionNode()
|
||||
{
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
m_apSubNode[i] = NULL;
|
||||
}
|
||||
|
||||
m_vBoundingMin.SetValue(0,0,0);
|
||||
m_vBoundingMax.SetValue(0,0,0);
|
||||
}
|
||||
|
||||
COctreeCollisionNode::~COctreeCollisionNode()
|
||||
{
|
||||
ReleaseSubNode();
|
||||
}
|
||||
|
||||
void COctreeCollisionNode::ReleaseSubNode()
|
||||
{
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
if (NULL != m_apSubNode[i])
|
||||
{
|
||||
delete m_apSubNode[i];
|
||||
m_apSubNode[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 자식노드가 전혀 없는 것이 리프 노드
|
||||
bool COctreeCollisionNode::IsLeafNode()
|
||||
{
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
if (NULL != m_apSubNode[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void COctreeCollisionNode::BuildSubNode(
|
||||
const std::vector< CollisionTriangleInfo >& vecTriangle,
|
||||
const size_t nMaximumRecursion, const size_t nMinPolyCount,
|
||||
size_t nCurrentRecursionLevel)
|
||||
{
|
||||
static size_t nProcessedTri = 0;
|
||||
|
||||
unsigned int i, j;
|
||||
|
||||
// recursion level 이 너무 깊거나, 포함된 face 갯수가 정해진것보다 작으면
|
||||
// 더이상 sub node 를 나누지 않는다 (재귀 종료 조건)
|
||||
if (nCurrentRecursionLevel >= nMaximumRecursion ||
|
||||
m_vecTriangleIndex.size() <= nMinPolyCount)
|
||||
{
|
||||
nProcessedTri += m_vecTriangleIndex.size();
|
||||
printf("\r%d / %d", nProcessedTri, vecTriangle.size());
|
||||
return;
|
||||
}
|
||||
|
||||
// 자식 노드들의 bounding box min/max
|
||||
Math::VECTOR3 aSubNodeBoundingMin[8];
|
||||
Math::VECTOR3 aSubNodeBoundingMax[8];
|
||||
|
||||
Math::VECTOR3 vMedian = (m_vBoundingMin + m_vBoundingMax)/2.0f;
|
||||
|
||||
// 바운딩 박스 값 설정
|
||||
for (i = 0; i < 8; ++i)
|
||||
{
|
||||
if (0 == (i & 1))
|
||||
{
|
||||
aSubNodeBoundingMin[i].x = m_vBoundingMin.x;
|
||||
aSubNodeBoundingMax[i].x = vMedian.x;
|
||||
}
|
||||
else
|
||||
{
|
||||
aSubNodeBoundingMin[i].x = vMedian.x;
|
||||
aSubNodeBoundingMax[i].x = m_vBoundingMax.x;
|
||||
}
|
||||
if (0 == (i & 2))
|
||||
{
|
||||
aSubNodeBoundingMin[i].y = m_vBoundingMin.y;
|
||||
aSubNodeBoundingMax[i].y = vMedian.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
aSubNodeBoundingMin[i].y = vMedian.y;
|
||||
aSubNodeBoundingMax[i].y = m_vBoundingMax.y;
|
||||
}
|
||||
if (0 == (i & 4))
|
||||
{
|
||||
aSubNodeBoundingMin[i].z = m_vBoundingMin.z;
|
||||
aSubNodeBoundingMax[i].z = vMedian.z;
|
||||
}
|
||||
else
|
||||
{
|
||||
aSubNodeBoundingMin[i].z = vMedian.z;
|
||||
aSubNodeBoundingMax[i].z = m_vBoundingMax.z;
|
||||
}
|
||||
}
|
||||
|
||||
// 넘겨받은 삼각형 인덱스에서 하부 노드로 내려갈것들과 이 노드에 저장될것들을 구분해낸다
|
||||
for (j = 0; j < m_vecTriangleIndex.size(); ++j)
|
||||
{
|
||||
// 삼각형 세 점 얻기
|
||||
const CollisionTriangleInfo &tri = vecTriangle[ m_vecTriangleIndex[j] ];
|
||||
const Math::VECTOR3 &vTri0 = tri.m_avVertex[0];
|
||||
const Math::VECTOR3 &vTri1 = tri.m_avVertex[1];
|
||||
const Math::VECTOR3 &vTri2 = tri.m_avVertex[2];
|
||||
|
||||
// 각 자식노드들에 대해 삼각형이 포함되는지 체크한다
|
||||
bool bIncludedInSubNode = false; // 자식 노드에 삼각형이 포함되는지 여부를 나타내는 플래그
|
||||
for (i = 0; i < 8; ++i)
|
||||
{
|
||||
if (Math::IsTriangleInAabb(aSubNodeBoundingMin[i], aSubNodeBoundingMax[i], vTri0, vTri1, vTri2))
|
||||
{
|
||||
// 노드가 할당되지 않았으면 할당
|
||||
COctreeCollisionNode* &pNode = m_apSubNode[i];
|
||||
if (NULL == pNode)
|
||||
{
|
||||
pNode = new COctreeCollisionNode;
|
||||
pNode->m_vBoundingMin = aSubNodeBoundingMin[i];
|
||||
pNode->m_vBoundingMax = aSubNodeBoundingMax[i];
|
||||
}
|
||||
|
||||
// 자식노드에 넘겨줄 삼각형 인덱스에 저장
|
||||
pNode->m_vecTriangleIndex.push_back(m_vecTriangleIndex[j]);
|
||||
bIncludedInSubNode = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!bIncludedInSubNode)
|
||||
{
|
||||
// 한 노드에 완전히 포함되는것이 아니라 다수 노드간에 걸치는 삼각형이므로,
|
||||
// triangle - AABB intersection 테스트를 한다
|
||||
for (i = 0; i < 8; ++i)
|
||||
{
|
||||
if (Math::CheckAabbTriangleIntersection(aSubNodeBoundingMin[i], aSubNodeBoundingMax[i], vTri0, vTri1, vTri2))
|
||||
{
|
||||
// 노드가 할당되지 않았으면 할당
|
||||
COctreeCollisionNode* &pNode = m_apSubNode[i];
|
||||
if (NULL == pNode)
|
||||
{
|
||||
pNode = new COctreeCollisionNode;
|
||||
pNode->m_vBoundingMin = aSubNodeBoundingMin[i];
|
||||
pNode->m_vBoundingMax = aSubNodeBoundingMax[i];
|
||||
}
|
||||
|
||||
// 자식노드에 넘겨줄 삼각형 인덱스에 저장
|
||||
pNode->m_vecTriangleIndex.push_back(m_vecTriangleIndex[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 삼각형 인덱스를 자식 노드에 모두 넘겨주었으므로 더 이상 인덱스를 들고 있을 필요가 없다
|
||||
m_vecTriangleIndex.clear();
|
||||
|
||||
// 삼각형이 있는 자식 노드는 BuildSubNode 를 호출한다
|
||||
for (i = 0; i < 8; ++i)
|
||||
{
|
||||
if (NULL != m_apSubNode[i])
|
||||
{
|
||||
m_apSubNode[i]->BuildSubNode(vecTriangle, nMaximumRecursion, nMinPolyCount, nCurrentRecursionLevel+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void COctreeCollisionNode::CollectCollidableNodes(
|
||||
const Math::VECTOR3& vSweptVolumeMin, const Math::VECTOR3& vSweptVolumeMax,
|
||||
std::vector< COctreeCollisionNode* >& vecCollidableNode)
|
||||
{
|
||||
if(!Math::CheckAabbAabbIntersection(vSweptVolumeMin, vSweptVolumeMax, m_vBoundingMin, m_vBoundingMax))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsLeafNode())
|
||||
{
|
||||
vecCollidableNode.push_back(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
if (NULL != m_apSubNode[i])
|
||||
{
|
||||
m_apSubNode[i]->CollectCollidableNodes(vSweptVolumeMin, vSweptVolumeMax, vecCollidableNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
COctreeCollider::COctreeCollider()
|
||||
{
|
||||
m_nColTriIndex = 0;
|
||||
}
|
||||
|
||||
COctreeCollider::~COctreeCollider()
|
||||
{
|
||||
}
|
||||
|
||||
void COctreeCollider::SetTriangleCount(unsigned int uiTriangleCount)
|
||||
{
|
||||
m_vecCollisionTriangle.resize(uiTriangleCount);
|
||||
}
|
||||
|
||||
void COctreeCollider::GetTriangleDataPtr(CollisionTriangleInfo*& pTriangleData)
|
||||
{
|
||||
if (m_vecCollisionTriangle.size() > 0)
|
||||
{
|
||||
pTriangleData = &(m_vecCollisionTriangle[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
pTriangleData = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool COctreeCollider::BuildOctree(const size_t nMaximumRecursion, const size_t nMinPolyCount)
|
||||
{
|
||||
unsigned int i, j;
|
||||
|
||||
if (0 == m_vecCollisionTriangle.size())
|
||||
{
|
||||
m_vCollisionBoundingMin.SetValue(0,0,0);
|
||||
m_vCollisionBoundingMax.SetValue(0,0,0);
|
||||
|
||||
return true; // 메시 데이터가 비어 있어도 일단은 정상종료..
|
||||
}
|
||||
|
||||
// 일단 기존 노드들을 삭제
|
||||
m_octreeRootNode.ReleaseSubNode();
|
||||
|
||||
// bounding min/max 구하기
|
||||
m_vCollisionBoundingMin = m_vecCollisionTriangle[0].m_avVertex[0];
|
||||
m_vCollisionBoundingMax = m_vecCollisionTriangle[0].m_avVertex[0];
|
||||
|
||||
for (i = 0; i < m_vecCollisionTriangle.size(); ++i)
|
||||
{
|
||||
for (j = 0; j < 3; ++j)
|
||||
{
|
||||
CrossM::Math::VECTOR3& v = m_vecCollisionTriangle[i].m_avVertex[j];
|
||||
|
||||
if (v.x < m_vCollisionBoundingMin.x) m_vCollisionBoundingMin.x = v.x;
|
||||
if (v.y < m_vCollisionBoundingMin.y) m_vCollisionBoundingMin.y = v.y;
|
||||
if (v.z < m_vCollisionBoundingMin.z) m_vCollisionBoundingMin.z = v.z;
|
||||
|
||||
if (v.x > m_vCollisionBoundingMax.x) m_vCollisionBoundingMax.x = v.x;
|
||||
if (v.y > m_vCollisionBoundingMax.y) m_vCollisionBoundingMax.y = v.y;
|
||||
if (v.z > m_vCollisionBoundingMax.z) m_vCollisionBoundingMax.z = v.z;
|
||||
}
|
||||
}
|
||||
|
||||
// octree root node 에 바운딩 박스 값 세팅
|
||||
m_octreeRootNode.m_vBoundingMin = m_vCollisionBoundingMin;
|
||||
m_octreeRootNode.m_vBoundingMax = m_vCollisionBoundingMax;
|
||||
|
||||
// octree root node 에 포함된 삼각형의 인덱스(전체)를 세팅
|
||||
m_octreeRootNode.m_vecTriangleIndex.resize(m_vecCollisionTriangle.size());
|
||||
for (i = 0; i < m_octreeRootNode.m_vecTriangleIndex.size(); ++i)
|
||||
{
|
||||
m_octreeRootNode.m_vecTriangleIndex[i] = i;
|
||||
}
|
||||
|
||||
// DWORD dwTime = timeGetTime();
|
||||
// for (i = 0; i < m_vecCollisionTriangle.size(); ++i)
|
||||
// {
|
||||
// CollisionTriangleInfo& tri = m_vecCollisionTriangle[i];
|
||||
// Math::VECTOR3& vTri0 = m_vecCollisionVertex[ tri.m_lIndex[0] ];
|
||||
// Math::VECTOR3& vTri1 = m_vecCollisionVertex[ tri.m_lIndex[1] ];
|
||||
// Math::VECTOR3& vTri2 = m_vecCollisionVertex[ tri.m_lIndex[2] ];
|
||||
//
|
||||
// Math::CheckAabbTriangleIntersection(m_vCollisionBoundingMin, m_vCollisionBoundingMax, vTri0, vTri1, vTri2);
|
||||
// }
|
||||
// DWORD dwElapsed = timeGetTime() - dwTime;
|
||||
//
|
||||
// dwTime = timeGetTime();
|
||||
// for (i = 0; i < m_vecCollisionTriangle.size(); ++i)
|
||||
// {
|
||||
// CollisionTriangleInfo& tri = m_vecCollisionTriangle[i];
|
||||
// Math::VECTOR3& vTri0 = m_vecCollisionVertex[ tri.m_lIndex[0] ];
|
||||
// Math::VECTOR3& vTri1 = m_vecCollisionVertex[ tri.m_lIndex[1] ];
|
||||
// Math::VECTOR3& vTri2 = m_vecCollisionVertex[ tri.m_lIndex[2] ];
|
||||
//
|
||||
// Math::IsTriangleInAabb(m_vCollisionBoundingMin, m_vCollisionBoundingMax, vTri0, vTri1, vTri2);
|
||||
// }
|
||||
// DWORD dwElapsed2 = timeGetTime() - dwTime;
|
||||
|
||||
// 하부 노드들을 생성
|
||||
m_octreeRootNode.BuildSubNode(m_vecCollisionTriangle, nMaximumRecursion, nMinPolyCount, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void COctreeCollider::GetCollisionRespondingPosition(
|
||||
Math::VECTOR3& vOutRespondingPos,
|
||||
const Math::VECTOR3& vPrevPos, const Math::VECTOR3& vNewPos,
|
||||
const Math::VECTOR3& vEllipsoidRadius,
|
||||
const unsigned int nRecursionLevel)
|
||||
{
|
||||
size_t i, j, nMinCollisionTriangleIndex;
|
||||
|
||||
// ellipsoid 가 쓸고 지나간 궤적을 커버하는 사각형(AABB)의 min/max 점
|
||||
Math::VECTOR3 vSweptVolumeMin, vSweptVolumeMax;
|
||||
|
||||
vSweptVolumeMin.x = min(vPrevPos.x, vNewPos.x) - vEllipsoidRadius.x;
|
||||
vSweptVolumeMax.x = max(vPrevPos.x, vNewPos.x) + vEllipsoidRadius.x;
|
||||
vSweptVolumeMin.y = min(vPrevPos.y, vNewPos.y) - vEllipsoidRadius.y;
|
||||
vSweptVolumeMax.y = max(vPrevPos.y, vNewPos.y) + vEllipsoidRadius.y;
|
||||
vSweptVolumeMin.z = min(vPrevPos.z, vNewPos.z) - vEllipsoidRadius.z;
|
||||
vSweptVolumeMax.z = max(vPrevPos.z, vNewPos.z) + vEllipsoidRadius.z;
|
||||
|
||||
m_vecpCollidableNode.clear();
|
||||
m_octreeRootNode.CollectCollidableNodes(vSweptVolumeMin, vSweptVolumeMax, m_vecpCollidableNode);
|
||||
|
||||
if (0 == m_vecpCollidableNode.size())
|
||||
{
|
||||
// 충돌 여지가 있는 삼각형조차 없다
|
||||
vOutRespondingPos = vNewPos;
|
||||
return;
|
||||
}
|
||||
|
||||
// ellipsoid 좌표계 상의 값들. sweep 시작, 끝점과 sweep 방향벡터, sweep 구간의 길이
|
||||
Math::VECTOR3 vESweepStart, vESweepEnd, vESweepPath;
|
||||
float fESweepLength;
|
||||
|
||||
vESweepStart.SetValue(vPrevPos.x/vEllipsoidRadius.x, vPrevPos.y/vEllipsoidRadius.y, vPrevPos.z/vEllipsoidRadius.z);
|
||||
vESweepEnd.SetValue(vNewPos.x/vEllipsoidRadius.x, vNewPos.y/vEllipsoidRadius.y, vNewPos.z/vEllipsoidRadius.z);
|
||||
Math::Subtract(vESweepPath, vESweepEnd, vESweepStart);
|
||||
fESweepLength = Math::GetLength(vESweepPath);
|
||||
// 움직임이 없는 경우
|
||||
if (fESweepLength < Math::F_EPSILON)
|
||||
{
|
||||
vOutRespondingPos = vPrevPos;
|
||||
return;
|
||||
}
|
||||
|
||||
// sweeping sphere 에 대한 정보를 설정
|
||||
Math::TriangSweepingSphere triAndSphere;
|
||||
triAndSphere.m_vSphereSweepStart = vESweepStart;
|
||||
triAndSphere.m_vSphereSweepPath = vESweepPath;
|
||||
triAndSphere.m_fSphereRadius = 1.0f; // ellipsoid 좌표계이므로 충돌타원체는 단위 구체로 변환되어짐
|
||||
|
||||
bool bCollision = false; // 선택된 노드들에서 충돌이 일어난 삼각형이 있는지 여부를 나타내는 플래그
|
||||
float fMinCollisionDistFactor = 9999.0f;// collision 이 일어난 점이 sweeping path 의 어느 위치인지 나타내는 숫자
|
||||
// 0 이 시작점, 1 이 끝점임
|
||||
Math::VECTOR3 vMinContactPoint; // fMinCollisionDistFactor 에서의 접점의 좌표. ellipsoid 좌표계임
|
||||
bool bMinContactInsideTriangle; // fMinCollisionDistFactor 에서 삼각형과의 접점이 삼각형 내부인지(모서리나 꼭지점이 아닌) 나타내는 플래그
|
||||
for (i = 0; i < m_vecpCollidableNode.size(); ++i)
|
||||
{
|
||||
COctreeCollisionNode& node = *(m_vecpCollidableNode[i]);
|
||||
for (j = 0; j < node.m_vecTriangleIndex.size(); ++j)
|
||||
{
|
||||
CollisionTriangleInfo& tri = m_vecCollisionTriangle[ node.m_vecTriangleIndex[j] ];
|
||||
|
||||
// 삼각형 정보를 설정
|
||||
Math::VECTOR3& vTri0 = tri.m_avVertex[0];
|
||||
Math::VECTOR3& vTri1 = tri.m_avVertex[1];
|
||||
Math::VECTOR3& vTri2 = tri.m_avVertex[2];
|
||||
// 삼각형 역시 ellipsoid 좌표계로 설정해줘야함을 잊지말것-ㅂ-
|
||||
triAndSphere.m_vTri0.SetValue(vTri0.x/vEllipsoidRadius.x, vTri0.y/vEllipsoidRadius.y, vTri0.z/vEllipsoidRadius.z);
|
||||
triAndSphere.m_vTri1.SetValue(vTri1.x/vEllipsoidRadius.x, vTri1.y/vEllipsoidRadius.y, vTri1.z/vEllipsoidRadius.z);
|
||||
triAndSphere.m_vTri2.SetValue(vTri2.x/vEllipsoidRadius.x, vTri2.y/vEllipsoidRadius.y, vTri2.z/vEllipsoidRadius.z);
|
||||
|
||||
float fCollisionDistFactor;
|
||||
Math::VECTOR3 vContactPoint;
|
||||
bool bContactInside;
|
||||
// 삼각형 - sweeping sphere 충돌 검사
|
||||
if (Math::CheckTriangleSweepingSphereCollision(fCollisionDistFactor, vContactPoint, bContactInside, triAndSphere))
|
||||
{
|
||||
// 충돌이면
|
||||
bCollision = true;
|
||||
|
||||
if(fCollisionDistFactor < fMinCollisionDistFactor)
|
||||
{
|
||||
vMinContactPoint = vContactPoint;
|
||||
fMinCollisionDistFactor = fCollisionDistFactor;
|
||||
nMinCollisionTriangleIndex = node.m_vecTriangleIndex[j];
|
||||
bMinContactInsideTriangle = bContactInside;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!bCollision)
|
||||
{
|
||||
// 충돌 없심
|
||||
vOutRespondingPos = vNewPos;
|
||||
return;
|
||||
}
|
||||
|
||||
m_nColTriIndex = nMinCollisionTriangleIndex;
|
||||
|
||||
// collision response phase
|
||||
Math::VECTOR3 vMovedPos; // 일단 충돌이 일어난점까지 이동한 위치
|
||||
Math::Lerp(vMovedPos, vPrevPos, vNewPos, fMinCollisionDistFactor); // 일단 이동 가능한 위치로 옮겨놓은 뒤..
|
||||
|
||||
// 원래 이동하려한 거리의 90% 이상을 진행했거나, recursion 이 4번 수행되었으면 종료한다.
|
||||
if (fMinCollisionDistFactor > 0.9f || nRecursionLevel >= 4)
|
||||
{
|
||||
vOutRespondingPos = vMovedPos;
|
||||
return;
|
||||
}
|
||||
|
||||
// 접점의 좌표를 ellipsoid 좌표계에서 원래 좌표계로 환산
|
||||
vMinContactPoint.x *= vEllipsoidRadius.x;
|
||||
vMinContactPoint.y *= vEllipsoidRadius.y;
|
||||
vMinContactPoint.z *= vEllipsoidRadius.z;
|
||||
|
||||
// 접접의 접평면을 구함
|
||||
Math::VECTOR3 vTangentPlaneNormal;
|
||||
if (bMinContactInsideTriangle)
|
||||
{
|
||||
// 삼각형과의 접점이 삼각형면 내에서라면, 충돌한 삼각형의 normal 을 그대로 이용한다
|
||||
CollisionTriangleInfo& colTriInfo = m_vecCollisionTriangle[nMinCollisionTriangleIndex];
|
||||
Math::VECTOR3& vCollTri0 = colTriInfo.m_avVertex[0];
|
||||
Math::VECTOR3& vCollTri1 = colTriInfo.m_avVertex[1];
|
||||
Math::VECTOR3& vCollTri2 = colTriInfo.m_avVertex[2];
|
||||
vTangentPlaneNormal = ((vCollTri1 - vCollTri0) ^ (vCollTri2 - vCollTri0));
|
||||
}
|
||||
else
|
||||
{
|
||||
// 모서리나 꼭지점과 충돌한 경우, 타원체의 접평면을 구하는 식을 이용해 접면의 normal 을 구한다
|
||||
Math::Subtract(vTangentPlaneNormal, vMovedPos, vMinContactPoint);
|
||||
vTangentPlaneNormal.x /= (vEllipsoidRadius.x*vEllipsoidRadius.x);
|
||||
vTangentPlaneNormal.y /= (vEllipsoidRadius.y*vEllipsoidRadius.y);
|
||||
vTangentPlaneNormal.z /= (vEllipsoidRadius.z*vEllipsoidRadius.z);
|
||||
Math::Normalize(vTangentPlaneNormal, vTangentPlaneNormal);
|
||||
}
|
||||
Math::Normalize(vTangentPlaneNormal, vTangentPlaneNormal);
|
||||
|
||||
// 충돌에 의해 진행하지 못하고 남은 이동성분 벡터를 구함
|
||||
Math::VECTOR3 vRemainder;
|
||||
Math::Subtract(vRemainder, vNewPos, vMovedPos);
|
||||
|
||||
// 충돌에 의해 움직일수 없어 사라지게 되는 이동성분을 구함
|
||||
float fVanishingComponentFactor = Math::DotProduct(vTangentPlaneNormal, vRemainder);
|
||||
Math::VECTOR3 vVanishingComponent;
|
||||
Math::Scale(vVanishingComponent, vTangentPlaneNormal, fVanishingComponentFactor);
|
||||
|
||||
// 남은 이동성분에서 움직일수 없는 방향으로의 성분을 제거
|
||||
Math::Subtract(vRemainder, vRemainder, vVanishingComponent);
|
||||
|
||||
// 남은 이동벡터만큼의 이동을 위해 충돌체크 재귀호출
|
||||
GetCollisionRespondingPosition(vOutRespondingPos, vMovedPos, vMovedPos+vRemainder, vEllipsoidRadius, nRecursionLevel+1);
|
||||
}
|
||||
|
||||
|
||||
void COctreeCollider::RenderCollidableNodeTriangles(IDirect3DDevice8* pDevice)
|
||||
{
|
||||
size_t nRenderTriCount; //j, i, nTriFilled;
|
||||
|
||||
if (0 == m_vecpCollidableNode.size())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// // 렌더할 삼각형의 갯수 구함
|
||||
// nRenderTriCount = 0;
|
||||
// for (i = 0; i < m_vecpCollidableNode.size(); ++i)
|
||||
// {
|
||||
// nRenderTriCount += m_vecpCollidableNode[i]->m_vecTriangleIndex.size();
|
||||
// }
|
||||
//
|
||||
// // 버텍스 공간 확보
|
||||
// m_vecRenderVertex.resize(nRenderTriCount*3);
|
||||
//
|
||||
// nTriFilled = 0;
|
||||
// for (i = 0; i < m_vecpCollidableNode.size(); ++i)
|
||||
// {
|
||||
// COctreeCollisionNode& node = *(m_vecpCollidableNode[i]);
|
||||
//
|
||||
// for (j = 0; j < node.m_vecTriangleIndex.size(); ++j)
|
||||
// {
|
||||
// size_t nTriIndex = node.m_vecTriangleIndex[j];
|
||||
// CollisionTriangleInfo& tri = m_vecCollisionTriangle[nTriIndex];
|
||||
//
|
||||
// m_vecRenderVertex[nTriFilled*3] = tri.m_avVertex[0];
|
||||
// m_vecRenderVertex[nTriFilled*3 + 1] = tri.m_avVertex[1];
|
||||
// m_vecRenderVertex[nTriFilled*3 + 2] = tri.m_avVertex[2];
|
||||
// ++nTriFilled;
|
||||
// }
|
||||
// }
|
||||
|
||||
nRenderTriCount = 1; // 충돌삼각형 1개만
|
||||
m_vecRenderVertex.resize(nRenderTriCount*3);
|
||||
CollisionTriangleInfo& tri = m_vecCollisionTriangle[m_nColTriIndex];
|
||||
|
||||
m_vecRenderVertex[0] = tri.m_avVertex[0];
|
||||
m_vecRenderVertex[1] = tri.m_avVertex[1];
|
||||
m_vecRenderVertex[2] = tri.m_avVertex[2];
|
||||
|
||||
D3DXMATRIX mTmp;
|
||||
D3DXMatrixIdentity(&mTmp);
|
||||
pDevice->SetTransform(D3DTS_WORLD, &mTmp);
|
||||
|
||||
DWORD dwFillMode, dwZFunc;
|
||||
pDevice->GetRenderState(D3DRS_FILLMODE, &dwFillMode);
|
||||
pDevice->GetRenderState(D3DRS_ZFUNC, &dwZFunc);
|
||||
pDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
|
||||
pDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
|
||||
pDevice->SetVertexShader(D3DFVF_XYZ);
|
||||
pDevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, (UINT)nRenderTriCount, &(m_vecRenderVertex[0]), sizeof(Math::VECTOR3));
|
||||
pDevice->SetRenderState(D3DRS_FILLMODE, dwFillMode);
|
||||
pDevice->SetRenderState(D3DRS_ZFUNC, dwZFunc);
|
||||
}
|
||||
|
||||
|
||||
}}
|
||||
Reference in New Issue
Block a user