diff --git a/Code/Code.rar b/Code/Code.rar
new file mode 100644
index 00000000..e048199d
Binary files /dev/null and b/Code/Code.rar differ
diff --git a/Code/DanBias.sln b/Code/DanBias.sln
index 7602cd2c..a8d583d8 100644
--- a/Code/DanBias.sln
+++ b/Code/DanBias.sln
@@ -5,6 +5,14 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OysterGraphics", "OysterGra
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OysterMath", "OysterMath\OysterMath.vcxproj", "{F10CBC03-9809-4CBA-95D8-327C287B18EE}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OysterPhysics3D", "OysterPhysics3D\OysterPhysics3D.vcxproj", "{4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Sound", "Sound\Sound.vcxproj", "{34D6295A-00DD-4B1A-8258-97DA2818EC26}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WindowManager", "WindowManager\WindowManager.vcxproj", "{35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Input", "Input\Input.vcxproj", "{7E3990D2-3D94-465C-B58D-64A74B3ECF9B}"
+EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Misc", "Misc\Misc.vcxproj", "{2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Network", "Network", "{C27B926E-B3EF-4990-8822-47580E43A0BE}"
@@ -15,289 +23,482 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OysterNetworkServer", "Netw
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NetworkDependencies", "Network\NetworkDependencies\NetworkDependencies.vcxproj", "{C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Tester", "Tester\Tester.vcxproj", "{1B3BEA4C-CF75-438A-9693-60FB8444BBF3}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Game", "Game", "{B0AFF0DC-5C7E-43DC-9586-CD4E38EB037B}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "aDanBiasGameLauncher", "Game\aDanBiasGameLauncher\aDanBiasGameLauncher.vcxproj", "{666FEA52-975F-41CD-B224-B19AF3C0ABBA}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GamePhysics", "GamePhysics\GamePhysics.vcxproj", "{104FA3E9-94D9-4E1D-A941-28A03BC8A095}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DanBiasGame", "Game\DanBiasGame\DanBiasGame.vcxproj", "{2A1BC987-AF42-4500-802D-89CD32FC1309}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DanBiasLauncher", "Game\DanBiasLauncher\DanBiasLauncher.vcxproj", "{8690FDDF-C5B7-4C42-A337-BD5243F29B85}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DanBiasServerLauncher", "Game\DanBiasServerLauncher\DanBiasServerLauncher.vcxproj", "{060B1890-CBF3-4808-BA99-A4776222093B}"
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Game", "Game", "{20720CA7-795C-45AD-A302-9383A6DD503A}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GameLogic", "Game\GameLogic\GameLogic.vcxproj", "{B1195BB9-B3A5-47F0-906C-8DEA384D1520}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GameProtocols", "Game\GameProtocols\GameProtocols.vcxproj", "{DA2AA800-ED64-4649-8B3B-E7F1E3968B78}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GameServer", "Game\GameServer\GameServer.vcxproj", "{143BD516-20A1-4890-A3E4-F8BFD02220E7}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DanBiasLauncher", "Game\DanBiasLauncher\DanBiasLauncher.vcxproj", "{8690FDDF-C5B7-4C42-A337-BD5243F29B85}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NetworkAPI", "Network\NetworkAPI\NetworkAPI.vcxproj", "{460D625F-2AC9-4559-B809-0BA89CEAEDF4}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GamePhysics", "GamePhysics\GamePhysics.vcxproj", "{104FA3E9-94D9-4E1D-A941-28A03BC8A095}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GameProtocols", "Game\GameProtocols\GameProtocols.vcxproj", "{DA2AA800-ED64-4649-8B3B-E7F1E3968B78}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Input", "Input\Input.vcxproj", "{7E3990D2-3D94-465C-B58D-64A74B3ECF9B}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DanBiasServerLauncher", "Game\DanBiasServerLauncher\DanBiasServerLauncher.vcxproj", "{060B1890-CBF3-4808-BA99-A4776222093B}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OysterPhysics3D", "OysterPhysics3D\OysterPhysics3D.vcxproj", "{4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GameServer", "Game\GameServer\GameServer.vcxproj", "{143BD516-20A1-4890-A3E4-F8BFD02220E7}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Sound", "Sound\Sound.vcxproj", "{34D6295A-00DD-4B1A-8258-97DA2818EC26}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "aDanBiasGameLauncher", "Game\aDanBiasGameLauncher\aDanBiasGameLauncher.vcxproj", "{666FEA52-975F-41CD-B224-B19AF3C0ABBA}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WindowManager", "WindowManager\WindowManager.vcxproj", "{35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}"
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Physics", "Physics", "{0D86E569-9C74-47F0-BDB2-390C0C9A084B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Mixed Platforms = Debug|Mixed Platforms
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
+ MinSizeRel|Mixed Platforms = MinSizeRel|Mixed Platforms
+ MinSizeRel|Win32 = MinSizeRel|Win32
+ MinSizeRel|x64 = MinSizeRel|x64
Release|Mixed Platforms = Release|Mixed Platforms
Release|Win32 = Release|Win32
Release|x64 = Release|x64
+ RelWithDebInfo|Mixed Platforms = RelWithDebInfo|Mixed Platforms
+ RelWithDebInfo|Win32 = RelWithDebInfo|Win32
+ RelWithDebInfo|x64 = RelWithDebInfo|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.Debug|Mixed Platforms.ActiveCfg = Release|x64
- {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.Debug|Mixed Platforms.Build.0 = Release|x64
+ {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+ {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.Debug|Mixed Platforms.Build.0 = Debug|Win32
{0EC83E64-230E-48EF-B08C-6AC9651B4F82}.Debug|Win32.ActiveCfg = Debug|Win32
{0EC83E64-230E-48EF-B08C-6AC9651B4F82}.Debug|Win32.Build.0 = Debug|Win32
- {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.Debug|Win32.Deploy.0 = Debug|Win32
- {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.Debug|x64.ActiveCfg = Release|x64
- {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.Debug|x64.Build.0 = Release|x64
- {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.Release|Mixed Platforms.ActiveCfg = Release|x64
- {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.Release|Mixed Platforms.Build.0 = Release|x64
+ {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.Debug|x64.ActiveCfg = Debug|x64
+ {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.Debug|x64.Build.0 = Debug|x64
+ {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.MinSizeRel|Mixed Platforms.ActiveCfg = Release|Win32
+ {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.MinSizeRel|Mixed Platforms.Build.0 = Release|Win32
+ {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.MinSizeRel|Win32.ActiveCfg = Release|Win32
+ {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.MinSizeRel|Win32.Build.0 = Release|Win32
+ {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.MinSizeRel|x64.ActiveCfg = Release|x64
+ {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.MinSizeRel|x64.Build.0 = Release|x64
+ {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.Release|Mixed Platforms.ActiveCfg = Release|Win32
+ {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.Release|Mixed Platforms.Build.0 = Release|Win32
{0EC83E64-230E-48EF-B08C-6AC9651B4F82}.Release|Win32.ActiveCfg = Release|Win32
{0EC83E64-230E-48EF-B08C-6AC9651B4F82}.Release|Win32.Build.0 = Release|Win32
{0EC83E64-230E-48EF-B08C-6AC9651B4F82}.Release|x64.ActiveCfg = Release|x64
{0EC83E64-230E-48EF-B08C-6AC9651B4F82}.Release|x64.Build.0 = Release|x64
- {F10CBC03-9809-4CBA-95D8-327C287B18EE}.Debug|Mixed Platforms.ActiveCfg = Release|x64
- {F10CBC03-9809-4CBA-95D8-327C287B18EE}.Debug|Mixed Platforms.Build.0 = Release|x64
+ {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.RelWithDebInfo|Mixed Platforms.ActiveCfg = Release|Win32
+ {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.RelWithDebInfo|Mixed Platforms.Build.0 = Release|Win32
+ {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32
+ {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.RelWithDebInfo|Win32.Build.0 = Release|Win32
+ {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.RelWithDebInfo|x64.ActiveCfg = Release|x64
+ {0EC83E64-230E-48EF-B08C-6AC9651B4F82}.RelWithDebInfo|x64.Build.0 = Release|x64
+ {F10CBC03-9809-4CBA-95D8-327C287B18EE}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+ {F10CBC03-9809-4CBA-95D8-327C287B18EE}.Debug|Mixed Platforms.Build.0 = Debug|Win32
{F10CBC03-9809-4CBA-95D8-327C287B18EE}.Debug|Win32.ActiveCfg = Debug|Win32
{F10CBC03-9809-4CBA-95D8-327C287B18EE}.Debug|Win32.Build.0 = Debug|Win32
- {F10CBC03-9809-4CBA-95D8-327C287B18EE}.Debug|Win32.Deploy.0 = Debug|Win32
- {F10CBC03-9809-4CBA-95D8-327C287B18EE}.Debug|x64.ActiveCfg = Release|x64
- {F10CBC03-9809-4CBA-95D8-327C287B18EE}.Debug|x64.Build.0 = Release|x64
- {F10CBC03-9809-4CBA-95D8-327C287B18EE}.Release|Mixed Platforms.ActiveCfg = Release|x64
- {F10CBC03-9809-4CBA-95D8-327C287B18EE}.Release|Mixed Platforms.Build.0 = Release|x64
+ {F10CBC03-9809-4CBA-95D8-327C287B18EE}.Debug|x64.ActiveCfg = Debug|x64
+ {F10CBC03-9809-4CBA-95D8-327C287B18EE}.Debug|x64.Build.0 = Debug|x64
+ {F10CBC03-9809-4CBA-95D8-327C287B18EE}.MinSizeRel|Mixed Platforms.ActiveCfg = Release|Win32
+ {F10CBC03-9809-4CBA-95D8-327C287B18EE}.MinSizeRel|Mixed Platforms.Build.0 = Release|Win32
+ {F10CBC03-9809-4CBA-95D8-327C287B18EE}.MinSizeRel|Win32.ActiveCfg = Release|Win32
+ {F10CBC03-9809-4CBA-95D8-327C287B18EE}.MinSizeRel|Win32.Build.0 = Release|Win32
+ {F10CBC03-9809-4CBA-95D8-327C287B18EE}.MinSizeRel|x64.ActiveCfg = Release|x64
+ {F10CBC03-9809-4CBA-95D8-327C287B18EE}.MinSizeRel|x64.Build.0 = Release|x64
+ {F10CBC03-9809-4CBA-95D8-327C287B18EE}.Release|Mixed Platforms.ActiveCfg = Release|Win32
+ {F10CBC03-9809-4CBA-95D8-327C287B18EE}.Release|Mixed Platforms.Build.0 = Release|Win32
{F10CBC03-9809-4CBA-95D8-327C287B18EE}.Release|Win32.ActiveCfg = Release|Win32
{F10CBC03-9809-4CBA-95D8-327C287B18EE}.Release|Win32.Build.0 = Release|Win32
{F10CBC03-9809-4CBA-95D8-327C287B18EE}.Release|x64.ActiveCfg = Release|x64
{F10CBC03-9809-4CBA-95D8-327C287B18EE}.Release|x64.Build.0 = Release|x64
- {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.Debug|Mixed Platforms.ActiveCfg = Release|x64
- {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.Debug|Mixed Platforms.Build.0 = Release|x64
- {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.Debug|Win32.ActiveCfg = Debug|Win32
- {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.Debug|Win32.Build.0 = Debug|Win32
- {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.Debug|Win32.Deploy.0 = Debug|Win32
- {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.Debug|x64.ActiveCfg = Release|x64
- {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.Debug|x64.Build.0 = Release|x64
- {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.Release|Mixed Platforms.ActiveCfg = Release|x64
- {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.Release|Mixed Platforms.Build.0 = Release|x64
- {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.Release|Win32.ActiveCfg = Release|Win32
- {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.Release|Win32.Build.0 = Release|Win32
- {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.Release|x64.ActiveCfg = Release|x64
- {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.Release|x64.Build.0 = Release|x64
- {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.Debug|Mixed Platforms.ActiveCfg = Release|x64
- {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.Debug|Mixed Platforms.Build.0 = Release|x64
- {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.Debug|Win32.ActiveCfg = Debug|Win32
- {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.Debug|Win32.Build.0 = Debug|Win32
- {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.Debug|x64.ActiveCfg = Release|x64
- {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.Debug|x64.Build.0 = Release|x64
- {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.Release|Mixed Platforms.ActiveCfg = Release|x64
- {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.Release|Mixed Platforms.Build.0 = Release|x64
- {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.Release|Win32.ActiveCfg = Release|Win32
- {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.Release|Win32.Build.0 = Release|Win32
- {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.Release|x64.ActiveCfg = Release|x64
- {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.Release|x64.Build.0 = Release|x64
- {6A066806-F43F-4B31-A4E3-57179674F460}.Debug|Mixed Platforms.ActiveCfg = Release|x64
- {6A066806-F43F-4B31-A4E3-57179674F460}.Debug|Mixed Platforms.Build.0 = Release|x64
- {6A066806-F43F-4B31-A4E3-57179674F460}.Debug|Win32.ActiveCfg = Debug|Win32
- {6A066806-F43F-4B31-A4E3-57179674F460}.Debug|Win32.Build.0 = Debug|Win32
- {6A066806-F43F-4B31-A4E3-57179674F460}.Debug|x64.ActiveCfg = Release|x64
- {6A066806-F43F-4B31-A4E3-57179674F460}.Debug|x64.Build.0 = Release|x64
- {6A066806-F43F-4B31-A4E3-57179674F460}.Release|Mixed Platforms.ActiveCfg = Release|x64
- {6A066806-F43F-4B31-A4E3-57179674F460}.Release|Mixed Platforms.Build.0 = Release|x64
- {6A066806-F43F-4B31-A4E3-57179674F460}.Release|Win32.ActiveCfg = Release|Win32
- {6A066806-F43F-4B31-A4E3-57179674F460}.Release|Win32.Build.0 = Release|Win32
- {6A066806-F43F-4B31-A4E3-57179674F460}.Release|x64.ActiveCfg = Release|x64
- {6A066806-F43F-4B31-A4E3-57179674F460}.Release|x64.Build.0 = Release|x64
- {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.Debug|Mixed Platforms.ActiveCfg = Release|x64
- {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.Debug|Mixed Platforms.Build.0 = Release|x64
- {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.Debug|Win32.ActiveCfg = Debug|Win32
- {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.Debug|Win32.Build.0 = Debug|Win32
- {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.Debug|x64.ActiveCfg = Release|x64
- {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.Debug|x64.Build.0 = Release|x64
- {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.Release|Mixed Platforms.ActiveCfg = Release|x64
- {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.Release|Mixed Platforms.Build.0 = Release|x64
- {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.Release|Win32.ActiveCfg = Release|Win32
- {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.Release|Win32.Build.0 = Release|Win32
- {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.Release|x64.ActiveCfg = Release|x64
- {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.Release|x64.Build.0 = Release|x64
- {1B3BEA4C-CF75-438A-9693-60FB8444BBF3}.Debug|Mixed Platforms.ActiveCfg = Release|Win32
- {1B3BEA4C-CF75-438A-9693-60FB8444BBF3}.Debug|Mixed Platforms.Build.0 = Release|Win32
- {1B3BEA4C-CF75-438A-9693-60FB8444BBF3}.Debug|Win32.ActiveCfg = Debug|Win32
- {1B3BEA4C-CF75-438A-9693-60FB8444BBF3}.Debug|Win32.Build.0 = Debug|Win32
- {1B3BEA4C-CF75-438A-9693-60FB8444BBF3}.Debug|x64.ActiveCfg = Release|Win32
- {1B3BEA4C-CF75-438A-9693-60FB8444BBF3}.Debug|x64.Build.0 = Release|Win32
- {1B3BEA4C-CF75-438A-9693-60FB8444BBF3}.Release|Mixed Platforms.ActiveCfg = Release|Win32
- {1B3BEA4C-CF75-438A-9693-60FB8444BBF3}.Release|Mixed Platforms.Build.0 = Release|Win32
- {1B3BEA4C-CF75-438A-9693-60FB8444BBF3}.Release|Win32.ActiveCfg = Release|Win32
- {1B3BEA4C-CF75-438A-9693-60FB8444BBF3}.Release|Win32.Build.0 = Release|Win32
- {1B3BEA4C-CF75-438A-9693-60FB8444BBF3}.Release|x64.ActiveCfg = Release|Win32
- {1B3BEA4C-CF75-438A-9693-60FB8444BBF3}.Release|x64.Build.0 = Release|Win32
- {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
- {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.Debug|Mixed Platforms.Build.0 = Debug|Win32
- {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.Debug|Win32.ActiveCfg = Debug|Win32
- {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.Debug|Win32.Build.0 = Debug|Win32
- {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.Debug|x64.ActiveCfg = Debug|x64
- {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.Debug|x64.Build.0 = Debug|x64
- {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.Release|Mixed Platforms.ActiveCfg = Release|Win32
- {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.Release|Mixed Platforms.Build.0 = Release|Win32
- {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.Release|Win32.ActiveCfg = Release|Win32
- {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.Release|Win32.Build.0 = Release|Win32
- {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.Release|x64.ActiveCfg = Release|x64
- {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.Release|x64.Build.0 = Release|x64
- {2A1BC987-AF42-4500-802D-89CD32FC1309}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
- {2A1BC987-AF42-4500-802D-89CD32FC1309}.Debug|Mixed Platforms.Build.0 = Debug|Win32
- {2A1BC987-AF42-4500-802D-89CD32FC1309}.Debug|Win32.ActiveCfg = Debug|Win32
- {2A1BC987-AF42-4500-802D-89CD32FC1309}.Debug|Win32.Build.0 = Debug|Win32
- {2A1BC987-AF42-4500-802D-89CD32FC1309}.Debug|x64.ActiveCfg = Debug|x64
- {2A1BC987-AF42-4500-802D-89CD32FC1309}.Debug|x64.Build.0 = Debug|x64
- {2A1BC987-AF42-4500-802D-89CD32FC1309}.Release|Mixed Platforms.ActiveCfg = Release|Win32
- {2A1BC987-AF42-4500-802D-89CD32FC1309}.Release|Mixed Platforms.Build.0 = Release|Win32
- {2A1BC987-AF42-4500-802D-89CD32FC1309}.Release|Win32.ActiveCfg = Release|Win32
- {2A1BC987-AF42-4500-802D-89CD32FC1309}.Release|Win32.Build.0 = Release|Win32
- {2A1BC987-AF42-4500-802D-89CD32FC1309}.Release|x64.ActiveCfg = Release|x64
- {2A1BC987-AF42-4500-802D-89CD32FC1309}.Release|x64.Build.0 = Release|x64
- {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
- {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.Debug|Mixed Platforms.Build.0 = Debug|Win32
- {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.Debug|Win32.ActiveCfg = Debug|Win32
- {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.Debug|Win32.Build.0 = Debug|Win32
- {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.Debug|x64.ActiveCfg = Debug|x64
- {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.Debug|x64.Build.0 = Debug|x64
- {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.Release|Mixed Platforms.ActiveCfg = Release|Win32
- {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.Release|Mixed Platforms.Build.0 = Release|Win32
- {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.Release|Win32.ActiveCfg = Release|Win32
- {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.Release|Win32.Build.0 = Release|Win32
- {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.Release|x64.ActiveCfg = Release|x64
- {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.Release|x64.Build.0 = Release|x64
- {060B1890-CBF3-4808-BA99-A4776222093B}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
- {060B1890-CBF3-4808-BA99-A4776222093B}.Debug|Mixed Platforms.Build.0 = Debug|Win32
- {060B1890-CBF3-4808-BA99-A4776222093B}.Debug|Win32.ActiveCfg = Debug|Win32
- {060B1890-CBF3-4808-BA99-A4776222093B}.Debug|Win32.Build.0 = Debug|Win32
- {060B1890-CBF3-4808-BA99-A4776222093B}.Debug|x64.ActiveCfg = Debug|x64
- {060B1890-CBF3-4808-BA99-A4776222093B}.Debug|x64.Build.0 = Debug|x64
- {060B1890-CBF3-4808-BA99-A4776222093B}.Release|Mixed Platforms.ActiveCfg = Release|Win32
- {060B1890-CBF3-4808-BA99-A4776222093B}.Release|Mixed Platforms.Build.0 = Release|Win32
- {060B1890-CBF3-4808-BA99-A4776222093B}.Release|Win32.ActiveCfg = Release|Win32
- {060B1890-CBF3-4808-BA99-A4776222093B}.Release|Win32.Build.0 = Release|Win32
- {060B1890-CBF3-4808-BA99-A4776222093B}.Release|x64.ActiveCfg = Release|x64
- {060B1890-CBF3-4808-BA99-A4776222093B}.Release|x64.Build.0 = Release|x64
- {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
- {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.Debug|Mixed Platforms.Build.0 = Debug|Win32
- {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.Debug|Win32.ActiveCfg = Debug|Win32
- {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.Debug|Win32.Build.0 = Debug|Win32
- {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.Debug|x64.ActiveCfg = Debug|x64
- {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.Debug|x64.Build.0 = Debug|x64
- {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.Release|Mixed Platforms.ActiveCfg = Release|Win32
- {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.Release|Mixed Platforms.Build.0 = Release|Win32
- {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.Release|Win32.ActiveCfg = Release|Win32
- {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.Release|Win32.Build.0 = Release|Win32
- {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.Release|x64.ActiveCfg = Release|x64
- {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.Release|x64.Build.0 = Release|x64
- {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
- {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.Debug|Mixed Platforms.Build.0 = Debug|Win32
- {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.Debug|Win32.ActiveCfg = Debug|Win32
- {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.Debug|Win32.Build.0 = Debug|Win32
- {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.Debug|x64.ActiveCfg = Debug|x64
- {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.Debug|x64.Build.0 = Debug|x64
- {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.Release|Mixed Platforms.ActiveCfg = Release|Win32
- {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.Release|Mixed Platforms.Build.0 = Release|Win32
- {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.Release|Win32.ActiveCfg = Release|Win32
- {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.Release|Win32.Build.0 = Release|Win32
- {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.Release|x64.ActiveCfg = Release|x64
- {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.Release|x64.Build.0 = Release|x64
- {143BD516-20A1-4890-A3E4-F8BFD02220E7}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
- {143BD516-20A1-4890-A3E4-F8BFD02220E7}.Debug|Mixed Platforms.Build.0 = Debug|Win32
- {143BD516-20A1-4890-A3E4-F8BFD02220E7}.Debug|Win32.ActiveCfg = Debug|Win32
- {143BD516-20A1-4890-A3E4-F8BFD02220E7}.Debug|Win32.Build.0 = Debug|Win32
- {143BD516-20A1-4890-A3E4-F8BFD02220E7}.Debug|x64.ActiveCfg = Debug|x64
- {143BD516-20A1-4890-A3E4-F8BFD02220E7}.Debug|x64.Build.0 = Debug|x64
- {143BD516-20A1-4890-A3E4-F8BFD02220E7}.Release|Mixed Platforms.ActiveCfg = Release|Win32
- {143BD516-20A1-4890-A3E4-F8BFD02220E7}.Release|Mixed Platforms.Build.0 = Release|Win32
- {143BD516-20A1-4890-A3E4-F8BFD02220E7}.Release|Win32.ActiveCfg = Release|Win32
- {143BD516-20A1-4890-A3E4-F8BFD02220E7}.Release|Win32.Build.0 = Release|Win32
- {143BD516-20A1-4890-A3E4-F8BFD02220E7}.Release|x64.ActiveCfg = Release|x64
- {143BD516-20A1-4890-A3E4-F8BFD02220E7}.Release|x64.Build.0 = Release|x64
- {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
- {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.Debug|Mixed Platforms.Build.0 = Debug|Win32
- {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.Debug|Win32.ActiveCfg = Debug|Win32
- {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.Debug|Win32.Build.0 = Debug|Win32
- {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.Debug|x64.ActiveCfg = Debug|x64
- {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.Debug|x64.Build.0 = Debug|x64
- {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.Release|Mixed Platforms.ActiveCfg = Release|Win32
- {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.Release|Mixed Platforms.Build.0 = Release|Win32
- {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.Release|Win32.ActiveCfg = Release|Win32
- {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.Release|Win32.Build.0 = Release|Win32
- {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.Release|x64.ActiveCfg = Release|x64
- {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.Release|x64.Build.0 = Release|x64
- {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
- {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.Debug|Mixed Platforms.Build.0 = Debug|Win32
- {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.Debug|Win32.ActiveCfg = Debug|Win32
- {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.Debug|Win32.Build.0 = Debug|Win32
- {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.Debug|x64.ActiveCfg = Debug|x64
- {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.Debug|x64.Build.0 = Debug|x64
- {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.Release|Mixed Platforms.ActiveCfg = Release|Win32
- {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.Release|Mixed Platforms.Build.0 = Release|Win32
- {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.Release|Win32.ActiveCfg = Release|Win32
- {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.Release|Win32.Build.0 = Release|Win32
- {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.Release|x64.ActiveCfg = Release|x64
- {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.Release|x64.Build.0 = Release|x64
- {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
- {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.Debug|Mixed Platforms.Build.0 = Debug|Win32
- {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.Debug|Win32.ActiveCfg = Debug|Win32
- {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.Debug|Win32.Build.0 = Debug|Win32
- {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.Debug|x64.ActiveCfg = Debug|x64
- {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.Debug|x64.Build.0 = Debug|x64
- {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.Release|Mixed Platforms.ActiveCfg = Release|Win32
- {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.Release|Mixed Platforms.Build.0 = Release|Win32
- {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.Release|Win32.ActiveCfg = Release|Win32
- {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.Release|Win32.Build.0 = Release|Win32
- {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.Release|x64.ActiveCfg = Release|x64
- {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.Release|x64.Build.0 = Release|x64
+ {F10CBC03-9809-4CBA-95D8-327C287B18EE}.RelWithDebInfo|Mixed Platforms.ActiveCfg = Release|Win32
+ {F10CBC03-9809-4CBA-95D8-327C287B18EE}.RelWithDebInfo|Mixed Platforms.Build.0 = Release|Win32
+ {F10CBC03-9809-4CBA-95D8-327C287B18EE}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32
+ {F10CBC03-9809-4CBA-95D8-327C287B18EE}.RelWithDebInfo|Win32.Build.0 = Release|Win32
+ {F10CBC03-9809-4CBA-95D8-327C287B18EE}.RelWithDebInfo|x64.ActiveCfg = Release|x64
+ {F10CBC03-9809-4CBA-95D8-327C287B18EE}.RelWithDebInfo|x64.Build.0 = Release|x64
{4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
{4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.Debug|Mixed Platforms.Build.0 = Debug|Win32
{4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.Debug|Win32.ActiveCfg = Debug|Win32
{4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.Debug|Win32.Build.0 = Debug|Win32
{4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.Debug|x64.ActiveCfg = Debug|x64
{4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.Debug|x64.Build.0 = Debug|x64
+ {4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.MinSizeRel|Mixed Platforms.ActiveCfg = Release|Win32
+ {4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.MinSizeRel|Mixed Platforms.Build.0 = Release|Win32
+ {4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.MinSizeRel|Win32.ActiveCfg = Release|Win32
+ {4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.MinSizeRel|Win32.Build.0 = Release|Win32
+ {4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.MinSizeRel|x64.ActiveCfg = Release|x64
+ {4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.MinSizeRel|x64.Build.0 = Release|x64
{4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.Release|Mixed Platforms.ActiveCfg = Release|Win32
{4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.Release|Mixed Platforms.Build.0 = Release|Win32
{4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.Release|Win32.ActiveCfg = Release|Win32
{4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.Release|Win32.Build.0 = Release|Win32
{4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.Release|x64.ActiveCfg = Release|x64
{4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.Release|x64.Build.0 = Release|x64
+ {4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.RelWithDebInfo|Mixed Platforms.ActiveCfg = Release|Win32
+ {4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.RelWithDebInfo|Mixed Platforms.Build.0 = Release|Win32
+ {4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32
+ {4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.RelWithDebInfo|Win32.Build.0 = Release|Win32
+ {4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.RelWithDebInfo|x64.ActiveCfg = Release|x64
+ {4285BD3F-3C6C-4670-B7AF-A29AFEF5F6A8}.RelWithDebInfo|x64.Build.0 = Release|x64
{34D6295A-00DD-4B1A-8258-97DA2818EC26}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
{34D6295A-00DD-4B1A-8258-97DA2818EC26}.Debug|Mixed Platforms.Build.0 = Debug|Win32
{34D6295A-00DD-4B1A-8258-97DA2818EC26}.Debug|Win32.ActiveCfg = Debug|Win32
{34D6295A-00DD-4B1A-8258-97DA2818EC26}.Debug|Win32.Build.0 = Debug|Win32
{34D6295A-00DD-4B1A-8258-97DA2818EC26}.Debug|x64.ActiveCfg = Debug|x64
{34D6295A-00DD-4B1A-8258-97DA2818EC26}.Debug|x64.Build.0 = Debug|x64
+ {34D6295A-00DD-4B1A-8258-97DA2818EC26}.MinSizeRel|Mixed Platforms.ActiveCfg = Release|Win32
+ {34D6295A-00DD-4B1A-8258-97DA2818EC26}.MinSizeRel|Mixed Platforms.Build.0 = Release|Win32
+ {34D6295A-00DD-4B1A-8258-97DA2818EC26}.MinSizeRel|Win32.ActiveCfg = Release|Win32
+ {34D6295A-00DD-4B1A-8258-97DA2818EC26}.MinSizeRel|Win32.Build.0 = Release|Win32
+ {34D6295A-00DD-4B1A-8258-97DA2818EC26}.MinSizeRel|x64.ActiveCfg = Release|x64
+ {34D6295A-00DD-4B1A-8258-97DA2818EC26}.MinSizeRel|x64.Build.0 = Release|x64
{34D6295A-00DD-4B1A-8258-97DA2818EC26}.Release|Mixed Platforms.ActiveCfg = Release|Win32
{34D6295A-00DD-4B1A-8258-97DA2818EC26}.Release|Mixed Platforms.Build.0 = Release|Win32
{34D6295A-00DD-4B1A-8258-97DA2818EC26}.Release|Win32.ActiveCfg = Release|Win32
{34D6295A-00DD-4B1A-8258-97DA2818EC26}.Release|Win32.Build.0 = Release|Win32
{34D6295A-00DD-4B1A-8258-97DA2818EC26}.Release|x64.ActiveCfg = Release|x64
{34D6295A-00DD-4B1A-8258-97DA2818EC26}.Release|x64.Build.0 = Release|x64
+ {34D6295A-00DD-4B1A-8258-97DA2818EC26}.RelWithDebInfo|Mixed Platforms.ActiveCfg = Release|Win32
+ {34D6295A-00DD-4B1A-8258-97DA2818EC26}.RelWithDebInfo|Mixed Platforms.Build.0 = Release|Win32
+ {34D6295A-00DD-4B1A-8258-97DA2818EC26}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32
+ {34D6295A-00DD-4B1A-8258-97DA2818EC26}.RelWithDebInfo|Win32.Build.0 = Release|Win32
+ {34D6295A-00DD-4B1A-8258-97DA2818EC26}.RelWithDebInfo|x64.ActiveCfg = Release|x64
+ {34D6295A-00DD-4B1A-8258-97DA2818EC26}.RelWithDebInfo|x64.Build.0 = Release|x64
{35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
{35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.Debug|Mixed Platforms.Build.0 = Debug|Win32
{35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.Debug|Win32.ActiveCfg = Debug|Win32
{35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.Debug|Win32.Build.0 = Debug|Win32
{35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.Debug|x64.ActiveCfg = Debug|x64
{35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.Debug|x64.Build.0 = Debug|x64
+ {35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.MinSizeRel|Mixed Platforms.ActiveCfg = Release|Win32
+ {35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.MinSizeRel|Mixed Platforms.Build.0 = Release|Win32
+ {35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.MinSizeRel|Win32.ActiveCfg = Release|Win32
+ {35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.MinSizeRel|Win32.Build.0 = Release|Win32
+ {35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.MinSizeRel|x64.ActiveCfg = Release|x64
+ {35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.MinSizeRel|x64.Build.0 = Release|x64
{35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.Release|Mixed Platforms.ActiveCfg = Release|Win32
{35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.Release|Mixed Platforms.Build.0 = Release|Win32
{35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.Release|Win32.ActiveCfg = Release|Win32
{35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.Release|Win32.Build.0 = Release|Win32
{35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.Release|x64.ActiveCfg = Release|x64
{35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.Release|x64.Build.0 = Release|x64
+ {35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.RelWithDebInfo|Mixed Platforms.ActiveCfg = Release|Win32
+ {35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.RelWithDebInfo|Mixed Platforms.Build.0 = Release|Win32
+ {35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32
+ {35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.RelWithDebInfo|Win32.Build.0 = Release|Win32
+ {35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.RelWithDebInfo|x64.ActiveCfg = Release|x64
+ {35AEA3C0-E0A7-4E1E-88CD-514AA5A442B1}.RelWithDebInfo|x64.Build.0 = Release|x64
+ {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+ {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.Debug|Mixed Platforms.Build.0 = Debug|Win32
+ {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.Debug|Win32.ActiveCfg = Debug|Win32
+ {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.Debug|Win32.Build.0 = Debug|Win32
+ {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.Debug|x64.ActiveCfg = Debug|x64
+ {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.Debug|x64.Build.0 = Debug|x64
+ {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.MinSizeRel|Mixed Platforms.ActiveCfg = Release|Win32
+ {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.MinSizeRel|Mixed Platforms.Build.0 = Release|Win32
+ {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.MinSizeRel|Win32.ActiveCfg = Release|Win32
+ {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.MinSizeRel|Win32.Build.0 = Release|Win32
+ {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.MinSizeRel|x64.ActiveCfg = Release|x64
+ {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.MinSizeRel|x64.Build.0 = Release|x64
+ {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.Release|Mixed Platforms.ActiveCfg = Release|Win32
+ {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.Release|Mixed Platforms.Build.0 = Release|Win32
+ {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.Release|Win32.ActiveCfg = Release|Win32
+ {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.Release|Win32.Build.0 = Release|Win32
+ {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.Release|x64.ActiveCfg = Release|x64
+ {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.Release|x64.Build.0 = Release|x64
+ {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.RelWithDebInfo|Mixed Platforms.ActiveCfg = Release|Win32
+ {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.RelWithDebInfo|Mixed Platforms.Build.0 = Release|Win32
+ {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32
+ {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.RelWithDebInfo|Win32.Build.0 = Release|Win32
+ {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.RelWithDebInfo|x64.ActiveCfg = Release|x64
+ {7E3990D2-3D94-465C-B58D-64A74B3ECF9B}.RelWithDebInfo|x64.Build.0 = Release|x64
+ {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+ {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.Debug|Mixed Platforms.Build.0 = Debug|Win32
+ {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.Debug|Win32.ActiveCfg = Debug|Win32
+ {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.Debug|Win32.Build.0 = Debug|Win32
+ {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.Debug|x64.ActiveCfg = Debug|x64
+ {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.Debug|x64.Build.0 = Debug|x64
+ {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.MinSizeRel|Mixed Platforms.ActiveCfg = Release|Win32
+ {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.MinSizeRel|Mixed Platforms.Build.0 = Release|Win32
+ {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.MinSizeRel|Win32.ActiveCfg = Release|Win32
+ {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.MinSizeRel|Win32.Build.0 = Release|Win32
+ {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.MinSizeRel|x64.ActiveCfg = Release|x64
+ {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.MinSizeRel|x64.Build.0 = Release|x64
+ {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.Release|Mixed Platforms.ActiveCfg = Release|Win32
+ {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.Release|Mixed Platforms.Build.0 = Release|Win32
+ {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.Release|Win32.ActiveCfg = Release|Win32
+ {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.Release|Win32.Build.0 = Release|Win32
+ {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.Release|x64.ActiveCfg = Release|x64
+ {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.Release|x64.Build.0 = Release|x64
+ {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.RelWithDebInfo|Mixed Platforms.ActiveCfg = Release|Win32
+ {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.RelWithDebInfo|Mixed Platforms.Build.0 = Release|Win32
+ {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32
+ {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.RelWithDebInfo|Win32.Build.0 = Release|Win32
+ {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.RelWithDebInfo|x64.ActiveCfg = Release|x64
+ {2EC4DDED-8F75-4C86-A10B-E1E8EB29F3EE}.RelWithDebInfo|x64.Build.0 = Release|x64
+ {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+ {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.Debug|Mixed Platforms.Build.0 = Debug|Win32
+ {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.Debug|Win32.ActiveCfg = Debug|Win32
+ {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.Debug|Win32.Build.0 = Debug|Win32
+ {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.Debug|x64.ActiveCfg = Debug|x64
+ {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.Debug|x64.Build.0 = Debug|x64
+ {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.MinSizeRel|Mixed Platforms.ActiveCfg = Release|Win32
+ {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.MinSizeRel|Win32.ActiveCfg = Release|Win32
+ {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.MinSizeRel|x64.ActiveCfg = Release|x64
+ {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.Release|Mixed Platforms.ActiveCfg = Release|Win32
+ {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.Release|Mixed Platforms.Build.0 = Release|Win32
+ {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.Release|Win32.ActiveCfg = Release|Win32
+ {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.Release|Win32.Build.0 = Release|Win32
+ {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.Release|x64.ActiveCfg = Release|x64
+ {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.Release|x64.Build.0 = Release|x64
+ {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.RelWithDebInfo|Mixed Platforms.ActiveCfg = Release|Win32
+ {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32
+ {838B25C2-D19E-49FE-8CB0-9A977CA3C7E8}.RelWithDebInfo|x64.ActiveCfg = Release|x64
+ {6A066806-F43F-4B31-A4E3-57179674F460}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+ {6A066806-F43F-4B31-A4E3-57179674F460}.Debug|Mixed Platforms.Build.0 = Debug|Win32
+ {6A066806-F43F-4B31-A4E3-57179674F460}.Debug|Win32.ActiveCfg = Debug|Win32
+ {6A066806-F43F-4B31-A4E3-57179674F460}.Debug|Win32.Build.0 = Debug|Win32
+ {6A066806-F43F-4B31-A4E3-57179674F460}.Debug|x64.ActiveCfg = Debug|x64
+ {6A066806-F43F-4B31-A4E3-57179674F460}.Debug|x64.Build.0 = Debug|x64
+ {6A066806-F43F-4B31-A4E3-57179674F460}.MinSizeRel|Mixed Platforms.ActiveCfg = Release|Win32
+ {6A066806-F43F-4B31-A4E3-57179674F460}.MinSizeRel|Win32.ActiveCfg = Release|Win32
+ {6A066806-F43F-4B31-A4E3-57179674F460}.MinSizeRel|x64.ActiveCfg = Release|x64
+ {6A066806-F43F-4B31-A4E3-57179674F460}.Release|Mixed Platforms.ActiveCfg = Release|Win32
+ {6A066806-F43F-4B31-A4E3-57179674F460}.Release|Mixed Platforms.Build.0 = Release|Win32
+ {6A066806-F43F-4B31-A4E3-57179674F460}.Release|Win32.ActiveCfg = Release|Win32
+ {6A066806-F43F-4B31-A4E3-57179674F460}.Release|Win32.Build.0 = Release|Win32
+ {6A066806-F43F-4B31-A4E3-57179674F460}.Release|x64.ActiveCfg = Release|x64
+ {6A066806-F43F-4B31-A4E3-57179674F460}.Release|x64.Build.0 = Release|x64
+ {6A066806-F43F-4B31-A4E3-57179674F460}.RelWithDebInfo|Mixed Platforms.ActiveCfg = Release|Win32
+ {6A066806-F43F-4B31-A4E3-57179674F460}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32
+ {6A066806-F43F-4B31-A4E3-57179674F460}.RelWithDebInfo|x64.ActiveCfg = Release|x64
+ {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+ {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.Debug|Mixed Platforms.Build.0 = Debug|Win32
+ {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.Debug|Win32.ActiveCfg = Debug|Win32
+ {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.Debug|Win32.Build.0 = Debug|Win32
+ {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.Debug|x64.ActiveCfg = Debug|x64
+ {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.Debug|x64.Build.0 = Debug|x64
+ {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.MinSizeRel|Mixed Platforms.ActiveCfg = Release|Win32
+ {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.MinSizeRel|Win32.ActiveCfg = Release|Win32
+ {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.MinSizeRel|x64.ActiveCfg = Release|x64
+ {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.Release|Mixed Platforms.ActiveCfg = Release|Win32
+ {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.Release|Mixed Platforms.Build.0 = Release|Win32
+ {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.Release|Win32.ActiveCfg = Release|Win32
+ {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.Release|Win32.Build.0 = Release|Win32
+ {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.Release|x64.ActiveCfg = Release|x64
+ {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.Release|x64.Build.0 = Release|x64
+ {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.RelWithDebInfo|Mixed Platforms.ActiveCfg = Release|Win32
+ {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32
+ {C5AA09D0-6594-4CD3-BD92-1D380C7B3B50}.RelWithDebInfo|x64.ActiveCfg = Release|x64
+ {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+ {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.Debug|Mixed Platforms.Build.0 = Debug|Win32
+ {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.Debug|Win32.ActiveCfg = Debug|Win32
+ {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.Debug|Win32.Build.0 = Debug|Win32
+ {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.Debug|x64.ActiveCfg = Debug|x64
+ {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.Debug|x64.Build.0 = Debug|x64
+ {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.MinSizeRel|Mixed Platforms.ActiveCfg = Release|Win32
+ {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.MinSizeRel|Mixed Platforms.Build.0 = Release|Win32
+ {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.MinSizeRel|Win32.ActiveCfg = Release|Win32
+ {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.MinSizeRel|Win32.Build.0 = Release|Win32
+ {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.MinSizeRel|x64.ActiveCfg = Release|x64
+ {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.MinSizeRel|x64.Build.0 = Release|x64
+ {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.Release|Mixed Platforms.ActiveCfg = Release|Win32
+ {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.Release|Mixed Platforms.Build.0 = Release|Win32
+ {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.Release|Win32.ActiveCfg = Release|Win32
+ {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.Release|Win32.Build.0 = Release|Win32
+ {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.Release|x64.ActiveCfg = Release|x64
+ {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.Release|x64.Build.0 = Release|x64
+ {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.RelWithDebInfo|Mixed Platforms.ActiveCfg = Release|Win32
+ {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.RelWithDebInfo|Mixed Platforms.Build.0 = Release|Win32
+ {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32
+ {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.RelWithDebInfo|Win32.Build.0 = Release|Win32
+ {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.RelWithDebInfo|x64.ActiveCfg = Release|x64
+ {104FA3E9-94D9-4E1D-A941-28A03BC8A095}.RelWithDebInfo|x64.Build.0 = Release|x64
+ {2A1BC987-AF42-4500-802D-89CD32FC1309}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+ {2A1BC987-AF42-4500-802D-89CD32FC1309}.Debug|Mixed Platforms.Build.0 = Debug|Win32
+ {2A1BC987-AF42-4500-802D-89CD32FC1309}.Debug|Win32.ActiveCfg = Debug|Win32
+ {2A1BC987-AF42-4500-802D-89CD32FC1309}.Debug|Win32.Build.0 = Debug|Win32
+ {2A1BC987-AF42-4500-802D-89CD32FC1309}.Debug|x64.ActiveCfg = Debug|x64
+ {2A1BC987-AF42-4500-802D-89CD32FC1309}.Debug|x64.Build.0 = Debug|x64
+ {2A1BC987-AF42-4500-802D-89CD32FC1309}.MinSizeRel|Mixed Platforms.ActiveCfg = Release|Win32
+ {2A1BC987-AF42-4500-802D-89CD32FC1309}.MinSizeRel|Mixed Platforms.Build.0 = Release|Win32
+ {2A1BC987-AF42-4500-802D-89CD32FC1309}.MinSizeRel|Win32.ActiveCfg = Release|Win32
+ {2A1BC987-AF42-4500-802D-89CD32FC1309}.MinSizeRel|Win32.Build.0 = Release|Win32
+ {2A1BC987-AF42-4500-802D-89CD32FC1309}.MinSizeRel|x64.ActiveCfg = Release|x64
+ {2A1BC987-AF42-4500-802D-89CD32FC1309}.MinSizeRel|x64.Build.0 = Release|x64
+ {2A1BC987-AF42-4500-802D-89CD32FC1309}.Release|Mixed Platforms.ActiveCfg = Release|Win32
+ {2A1BC987-AF42-4500-802D-89CD32FC1309}.Release|Mixed Platforms.Build.0 = Release|Win32
+ {2A1BC987-AF42-4500-802D-89CD32FC1309}.Release|Win32.ActiveCfg = Release|Win32
+ {2A1BC987-AF42-4500-802D-89CD32FC1309}.Release|Win32.Build.0 = Release|Win32
+ {2A1BC987-AF42-4500-802D-89CD32FC1309}.Release|x64.ActiveCfg = Release|x64
+ {2A1BC987-AF42-4500-802D-89CD32FC1309}.Release|x64.Build.0 = Release|x64
+ {2A1BC987-AF42-4500-802D-89CD32FC1309}.RelWithDebInfo|Mixed Platforms.ActiveCfg = Release|Win32
+ {2A1BC987-AF42-4500-802D-89CD32FC1309}.RelWithDebInfo|Mixed Platforms.Build.0 = Release|Win32
+ {2A1BC987-AF42-4500-802D-89CD32FC1309}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32
+ {2A1BC987-AF42-4500-802D-89CD32FC1309}.RelWithDebInfo|Win32.Build.0 = Release|Win32
+ {2A1BC987-AF42-4500-802D-89CD32FC1309}.RelWithDebInfo|x64.ActiveCfg = Release|x64
+ {2A1BC987-AF42-4500-802D-89CD32FC1309}.RelWithDebInfo|x64.Build.0 = Release|x64
+ {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+ {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.Debug|Mixed Platforms.Build.0 = Debug|Win32
+ {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.Debug|Win32.ActiveCfg = Debug|Win32
+ {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.Debug|Win32.Build.0 = Debug|Win32
+ {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.Debug|x64.ActiveCfg = Debug|x64
+ {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.Debug|x64.Build.0 = Debug|x64
+ {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.MinSizeRel|Mixed Platforms.ActiveCfg = Release|Win32
+ {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.MinSizeRel|Mixed Platforms.Build.0 = Release|Win32
+ {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.MinSizeRel|Win32.ActiveCfg = Release|Win32
+ {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.MinSizeRel|Win32.Build.0 = Release|Win32
+ {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.MinSizeRel|x64.ActiveCfg = Release|x64
+ {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.MinSizeRel|x64.Build.0 = Release|x64
+ {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.Release|Mixed Platforms.ActiveCfg = Release|Win32
+ {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.Release|Mixed Platforms.Build.0 = Release|Win32
+ {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.Release|Win32.ActiveCfg = Release|Win32
+ {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.Release|Win32.Build.0 = Release|Win32
+ {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.Release|x64.ActiveCfg = Release|x64
+ {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.Release|x64.Build.0 = Release|x64
+ {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.RelWithDebInfo|Mixed Platforms.ActiveCfg = Release|Win32
+ {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.RelWithDebInfo|Mixed Platforms.Build.0 = Release|Win32
+ {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32
+ {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.RelWithDebInfo|Win32.Build.0 = Release|Win32
+ {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.RelWithDebInfo|x64.ActiveCfg = Release|x64
+ {B1195BB9-B3A5-47F0-906C-8DEA384D1520}.RelWithDebInfo|x64.Build.0 = Release|x64
+ {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+ {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.Debug|Mixed Platforms.Build.0 = Debug|Win32
+ {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.Debug|Win32.ActiveCfg = Debug|Win32
+ {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.Debug|Win32.Build.0 = Debug|Win32
+ {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.Debug|x64.ActiveCfg = Debug|x64
+ {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.Debug|x64.Build.0 = Debug|x64
+ {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.MinSizeRel|Mixed Platforms.ActiveCfg = Release|Win32
+ {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.MinSizeRel|Mixed Platforms.Build.0 = Release|Win32
+ {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.MinSizeRel|Win32.ActiveCfg = Release|Win32
+ {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.MinSizeRel|Win32.Build.0 = Release|Win32
+ {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.MinSizeRel|x64.ActiveCfg = Release|x64
+ {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.MinSizeRel|x64.Build.0 = Release|x64
+ {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.Release|Mixed Platforms.ActiveCfg = Release|Win32
+ {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.Release|Mixed Platforms.Build.0 = Release|Win32
+ {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.Release|Win32.ActiveCfg = Release|Win32
+ {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.Release|Win32.Build.0 = Release|Win32
+ {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.Release|x64.ActiveCfg = Release|x64
+ {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.Release|x64.Build.0 = Release|x64
+ {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.RelWithDebInfo|Mixed Platforms.ActiveCfg = Release|Win32
+ {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.RelWithDebInfo|Mixed Platforms.Build.0 = Release|Win32
+ {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32
+ {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.RelWithDebInfo|Win32.Build.0 = Release|Win32
+ {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.RelWithDebInfo|x64.ActiveCfg = Release|x64
+ {8690FDDF-C5B7-4C42-A337-BD5243F29B85}.RelWithDebInfo|x64.Build.0 = Release|x64
+ {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+ {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.Debug|Mixed Platforms.Build.0 = Debug|Win32
+ {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.Debug|Win32.ActiveCfg = Debug|Win32
+ {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.Debug|Win32.Build.0 = Debug|Win32
+ {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.Debug|x64.ActiveCfg = Debug|x64
+ {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.Debug|x64.Build.0 = Debug|x64
+ {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.MinSizeRel|Mixed Platforms.ActiveCfg = Release|Win32
+ {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.MinSizeRel|Mixed Platforms.Build.0 = Release|Win32
+ {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.MinSizeRel|Win32.ActiveCfg = Release|Win32
+ {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.MinSizeRel|Win32.Build.0 = Release|Win32
+ {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.MinSizeRel|x64.ActiveCfg = Release|x64
+ {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.MinSizeRel|x64.Build.0 = Release|x64
+ {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.Release|Mixed Platforms.ActiveCfg = Release|Win32
+ {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.Release|Mixed Platforms.Build.0 = Release|Win32
+ {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.Release|Win32.ActiveCfg = Release|Win32
+ {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.Release|Win32.Build.0 = Release|Win32
+ {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.Release|x64.ActiveCfg = Release|x64
+ {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.Release|x64.Build.0 = Release|x64
+ {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.RelWithDebInfo|Mixed Platforms.ActiveCfg = Release|Win32
+ {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.RelWithDebInfo|Mixed Platforms.Build.0 = Release|Win32
+ {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32
+ {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.RelWithDebInfo|Win32.Build.0 = Release|Win32
+ {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.RelWithDebInfo|x64.ActiveCfg = Release|x64
+ {460D625F-2AC9-4559-B809-0BA89CEAEDF4}.RelWithDebInfo|x64.Build.0 = Release|x64
+ {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+ {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.Debug|Mixed Platforms.Build.0 = Debug|Win32
+ {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.Debug|Win32.ActiveCfg = Debug|Win32
+ {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.Debug|Win32.Build.0 = Debug|Win32
+ {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.Debug|x64.ActiveCfg = Debug|x64
+ {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.Debug|x64.Build.0 = Debug|x64
+ {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.MinSizeRel|Mixed Platforms.ActiveCfg = Release|Win32
+ {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.MinSizeRel|Mixed Platforms.Build.0 = Release|Win32
+ {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.MinSizeRel|Win32.ActiveCfg = Release|Win32
+ {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.MinSizeRel|Win32.Build.0 = Release|Win32
+ {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.MinSizeRel|x64.ActiveCfg = Release|x64
+ {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.MinSizeRel|x64.Build.0 = Release|x64
+ {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.Release|Mixed Platforms.ActiveCfg = Release|Win32
+ {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.Release|Mixed Platforms.Build.0 = Release|Win32
+ {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.Release|Win32.ActiveCfg = Release|Win32
+ {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.Release|Win32.Build.0 = Release|Win32
+ {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.Release|x64.ActiveCfg = Release|x64
+ {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.Release|x64.Build.0 = Release|x64
+ {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.RelWithDebInfo|Mixed Platforms.ActiveCfg = Release|Win32
+ {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.RelWithDebInfo|Mixed Platforms.Build.0 = Release|Win32
+ {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32
+ {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.RelWithDebInfo|Win32.Build.0 = Release|Win32
+ {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.RelWithDebInfo|x64.ActiveCfg = Release|x64
+ {DA2AA800-ED64-4649-8B3B-E7F1E3968B78}.RelWithDebInfo|x64.Build.0 = Release|x64
+ {060B1890-CBF3-4808-BA99-A4776222093B}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+ {060B1890-CBF3-4808-BA99-A4776222093B}.Debug|Mixed Platforms.Build.0 = Debug|Win32
+ {060B1890-CBF3-4808-BA99-A4776222093B}.Debug|Win32.ActiveCfg = Debug|Win32
+ {060B1890-CBF3-4808-BA99-A4776222093B}.Debug|Win32.Build.0 = Debug|Win32
+ {060B1890-CBF3-4808-BA99-A4776222093B}.Debug|x64.ActiveCfg = Debug|x64
+ {060B1890-CBF3-4808-BA99-A4776222093B}.Debug|x64.Build.0 = Debug|x64
+ {060B1890-CBF3-4808-BA99-A4776222093B}.MinSizeRel|Mixed Platforms.ActiveCfg = Release|Win32
+ {060B1890-CBF3-4808-BA99-A4776222093B}.MinSizeRel|Mixed Platforms.Build.0 = Release|Win32
+ {060B1890-CBF3-4808-BA99-A4776222093B}.MinSizeRel|Win32.ActiveCfg = Release|Win32
+ {060B1890-CBF3-4808-BA99-A4776222093B}.MinSizeRel|Win32.Build.0 = Release|Win32
+ {060B1890-CBF3-4808-BA99-A4776222093B}.MinSizeRel|x64.ActiveCfg = Release|x64
+ {060B1890-CBF3-4808-BA99-A4776222093B}.MinSizeRel|x64.Build.0 = Release|x64
+ {060B1890-CBF3-4808-BA99-A4776222093B}.Release|Mixed Platforms.ActiveCfg = Release|Win32
+ {060B1890-CBF3-4808-BA99-A4776222093B}.Release|Mixed Platforms.Build.0 = Release|Win32
+ {060B1890-CBF3-4808-BA99-A4776222093B}.Release|Win32.ActiveCfg = Release|Win32
+ {060B1890-CBF3-4808-BA99-A4776222093B}.Release|Win32.Build.0 = Release|Win32
+ {060B1890-CBF3-4808-BA99-A4776222093B}.Release|x64.ActiveCfg = Release|x64
+ {060B1890-CBF3-4808-BA99-A4776222093B}.Release|x64.Build.0 = Release|x64
+ {060B1890-CBF3-4808-BA99-A4776222093B}.RelWithDebInfo|Mixed Platforms.ActiveCfg = Release|Win32
+ {060B1890-CBF3-4808-BA99-A4776222093B}.RelWithDebInfo|Mixed Platforms.Build.0 = Release|Win32
+ {060B1890-CBF3-4808-BA99-A4776222093B}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32
+ {060B1890-CBF3-4808-BA99-A4776222093B}.RelWithDebInfo|Win32.Build.0 = Release|Win32
+ {060B1890-CBF3-4808-BA99-A4776222093B}.RelWithDebInfo|x64.ActiveCfg = Release|x64
+ {060B1890-CBF3-4808-BA99-A4776222093B}.RelWithDebInfo|x64.Build.0 = Release|x64
+ {143BD516-20A1-4890-A3E4-F8BFD02220E7}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+ {143BD516-20A1-4890-A3E4-F8BFD02220E7}.Debug|Mixed Platforms.Build.0 = Debug|Win32
+ {143BD516-20A1-4890-A3E4-F8BFD02220E7}.Debug|Win32.ActiveCfg = Debug|Win32
+ {143BD516-20A1-4890-A3E4-F8BFD02220E7}.Debug|Win32.Build.0 = Debug|Win32
+ {143BD516-20A1-4890-A3E4-F8BFD02220E7}.Debug|x64.ActiveCfg = Debug|x64
+ {143BD516-20A1-4890-A3E4-F8BFD02220E7}.Debug|x64.Build.0 = Debug|x64
+ {143BD516-20A1-4890-A3E4-F8BFD02220E7}.MinSizeRel|Mixed Platforms.ActiveCfg = Release|Win32
+ {143BD516-20A1-4890-A3E4-F8BFD02220E7}.MinSizeRel|Mixed Platforms.Build.0 = Release|Win32
+ {143BD516-20A1-4890-A3E4-F8BFD02220E7}.MinSizeRel|Win32.ActiveCfg = Release|Win32
+ {143BD516-20A1-4890-A3E4-F8BFD02220E7}.MinSizeRel|Win32.Build.0 = Release|Win32
+ {143BD516-20A1-4890-A3E4-F8BFD02220E7}.MinSizeRel|x64.ActiveCfg = Release|x64
+ {143BD516-20A1-4890-A3E4-F8BFD02220E7}.MinSizeRel|x64.Build.0 = Release|x64
+ {143BD516-20A1-4890-A3E4-F8BFD02220E7}.Release|Mixed Platforms.ActiveCfg = Release|Win32
+ {143BD516-20A1-4890-A3E4-F8BFD02220E7}.Release|Mixed Platforms.Build.0 = Release|Win32
+ {143BD516-20A1-4890-A3E4-F8BFD02220E7}.Release|Win32.ActiveCfg = Release|Win32
+ {143BD516-20A1-4890-A3E4-F8BFD02220E7}.Release|Win32.Build.0 = Release|Win32
+ {143BD516-20A1-4890-A3E4-F8BFD02220E7}.Release|x64.ActiveCfg = Release|x64
+ {143BD516-20A1-4890-A3E4-F8BFD02220E7}.Release|x64.Build.0 = Release|x64
+ {143BD516-20A1-4890-A3E4-F8BFD02220E7}.RelWithDebInfo|Mixed Platforms.ActiveCfg = Release|Win32
+ {143BD516-20A1-4890-A3E4-F8BFD02220E7}.RelWithDebInfo|Mixed Platforms.Build.0 = Release|Win32
+ {143BD516-20A1-4890-A3E4-F8BFD02220E7}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32
+ {143BD516-20A1-4890-A3E4-F8BFD02220E7}.RelWithDebInfo|Win32.Build.0 = Release|Win32
+ {143BD516-20A1-4890-A3E4-F8BFD02220E7}.RelWithDebInfo|x64.ActiveCfg = Release|x64
+ {143BD516-20A1-4890-A3E4-F8BFD02220E7}.RelWithDebInfo|x64.Build.0 = Release|x64
+ {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
+ {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.Debug|Mixed Platforms.Build.0 = Debug|Win32
+ {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.Debug|Win32.ActiveCfg = Debug|Win32
+ {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.Debug|Win32.Build.0 = Debug|Win32
+ {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.Debug|x64.ActiveCfg = Debug|x64
+ {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.Debug|x64.Build.0 = Debug|x64
+ {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.MinSizeRel|Mixed Platforms.ActiveCfg = Release|Win32
+ {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.MinSizeRel|Mixed Platforms.Build.0 = Release|Win32
+ {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.MinSizeRel|Win32.ActiveCfg = Release|Win32
+ {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.MinSizeRel|Win32.Build.0 = Release|Win32
+ {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.MinSizeRel|x64.ActiveCfg = Release|x64
+ {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.MinSizeRel|x64.Build.0 = Release|x64
+ {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.Release|Mixed Platforms.ActiveCfg = Release|Win32
+ {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.Release|Mixed Platforms.Build.0 = Release|Win32
+ {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.Release|Win32.ActiveCfg = Release|Win32
+ {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.Release|Win32.Build.0 = Release|Win32
+ {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.Release|x64.ActiveCfg = Release|x64
+ {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.Release|x64.Build.0 = Release|x64
+ {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.RelWithDebInfo|Mixed Platforms.ActiveCfg = Release|Win32
+ {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.RelWithDebInfo|Mixed Platforms.Build.0 = Release|Win32
+ {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.RelWithDebInfo|Win32.ActiveCfg = Release|Win32
+ {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.RelWithDebInfo|Win32.Build.0 = Release|Win32
+ {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.RelWithDebInfo|x64.ActiveCfg = Release|x64
+ {666FEA52-975F-41CD-B224-B19AF3C0ABBA}.RelWithDebInfo|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -307,12 +508,12 @@ Global
{6A066806-F43F-4B31-A4E3-57179674F460} = {C27B926E-B3EF-4990-8822-47580E43A0BE}
{C5AA09D0-6594-4CD3-BD92-1D380C7B3B50} = {C27B926E-B3EF-4990-8822-47580E43A0BE}
{460D625F-2AC9-4559-B809-0BA89CEAEDF4} = {C27B926E-B3EF-4990-8822-47580E43A0BE}
- {666FEA52-975F-41CD-B224-B19AF3C0ABBA} = {B0AFF0DC-5C7E-43DC-9586-CD4E38EB037B}
- {2A1BC987-AF42-4500-802D-89CD32FC1309} = {B0AFF0DC-5C7E-43DC-9586-CD4E38EB037B}
- {8690FDDF-C5B7-4C42-A337-BD5243F29B85} = {B0AFF0DC-5C7E-43DC-9586-CD4E38EB037B}
- {060B1890-CBF3-4808-BA99-A4776222093B} = {B0AFF0DC-5C7E-43DC-9586-CD4E38EB037B}
- {B1195BB9-B3A5-47F0-906C-8DEA384D1520} = {B0AFF0DC-5C7E-43DC-9586-CD4E38EB037B}
- {DA2AA800-ED64-4649-8B3B-E7F1E3968B78} = {B0AFF0DC-5C7E-43DC-9586-CD4E38EB037B}
- {143BD516-20A1-4890-A3E4-F8BFD02220E7} = {B0AFF0DC-5C7E-43DC-9586-CD4E38EB037B}
+ {2A1BC987-AF42-4500-802D-89CD32FC1309} = {20720CA7-795C-45AD-A302-9383A6DD503A}
+ {B1195BB9-B3A5-47F0-906C-8DEA384D1520} = {20720CA7-795C-45AD-A302-9383A6DD503A}
+ {8690FDDF-C5B7-4C42-A337-BD5243F29B85} = {20720CA7-795C-45AD-A302-9383A6DD503A}
+ {DA2AA800-ED64-4649-8B3B-E7F1E3968B78} = {20720CA7-795C-45AD-A302-9383A6DD503A}
+ {060B1890-CBF3-4808-BA99-A4776222093B} = {20720CA7-795C-45AD-A302-9383A6DD503A}
+ {143BD516-20A1-4890-A3E4-F8BFD02220E7} = {20720CA7-795C-45AD-A302-9383A6DD503A}
+ {666FEA52-975F-41CD-B224-B19AF3C0ABBA} = {20720CA7-795C-45AD-A302-9383A6DD503A}
EndGlobalSection
EndGlobal
diff --git a/Code/Game/DanBiasGame/DanBiasGame.vcxproj b/Code/Game/DanBiasGame/DanBiasGame.vcxproj
index 01a92481..83806118 100644
--- a/Code/Game/DanBiasGame/DanBiasGame.vcxproj
+++ b/Code/Game/DanBiasGame/DanBiasGame.vcxproj
@@ -205,6 +205,10 @@
+
+
+
+
@@ -219,6 +223,11 @@
+
+
+
+
+
diff --git a/Code/Game/DanBiasGame/DanBiasGame_Impl.cpp b/Code/Game/DanBiasGame/DanBiasGame_Impl.cpp
index 74d5f049..ccb80d85 100644
--- a/Code/Game/DanBiasGame/DanBiasGame_Impl.cpp
+++ b/Code/Game/DanBiasGame/DanBiasGame_Impl.cpp
@@ -17,6 +17,9 @@
#include "vld.h"
#include "GameClientRecieverFunc.h"
+#include "../Misc/EventHandler/EventHandler.h"
+using namespace Oyster::Event;
+
namespace DanBias
{
@@ -138,8 +141,6 @@ namespace DanBias
HRESULT DanBiasGame::Update(float deltaTime)
{
-
-
m_data->inputObj->Update();
if(m_data->serverOwner)
diff --git a/Code/Game/DanBiasGame/GameClientRecieverFunc.h b/Code/Game/DanBiasGame/GameClientRecieverFunc.h
index 15b0cdab..3ea449ec 100644
--- a/Code/Game/DanBiasGame/GameClientRecieverFunc.h
+++ b/Code/Game/DanBiasGame/GameClientRecieverFunc.h
@@ -38,34 +38,6 @@ namespace DanBias
}
}
break;
- case protocol_Gameplay_PlayerMovement:
- {
- Client::GameClientState::KeyInput* protocolData = new Client::GameClientState::KeyInput;
- for(int i = 0; i< 6; i++)
- {
- protocolData->key[i] = p[i+1].value.netBool;
- }
-
- if(dynamic_cast(gameClientState))
- ((Client::GameState*)gameClientState)->Protocol(protocolData);
- delete protocolData;
- protocolData = NULL;
- }
- break;
- //case protocol_Gameplay_PlayerPosition:
- // {
- // Client::GameClientState::PlayerPos* protocolData = new Client::GameClientState::PlayerPos;
- // for(int i = 0; i< 3; i++)
- // {
- // protocolData->playerPos[i] = p[i].value.netFloat;
- // }
- // if(dynamic_cast(gameClientState))
- // ((Client::GameState*)gameClientState)->Protocol(protocolData);
- // delete protocolData;
- // protocolData = NULL;
- // }
- // break;
-
case protocol_Gameplay_ObjectCreate:
{
Client::GameClientState::NewObj protocolData;// = new Client::GameClientState::NewObj;
@@ -110,11 +82,24 @@ namespace DanBias
((Client::GameState*)gameClientState)->Protocol(&protocolData);
}
break;
+ case protocol_Gameplay_ObjectPositionRotation:
+ {
+
+ Client::GameClientState::ObjPos protocolData;
+ protocolData.object_ID = p[1].value.netInt;
+ for(int i = 0; i< 16; i++)
+ {
+ protocolData.worldPos[i] = p[i+2].value.netFloat;
+ }
+
+ if(dynamic_cast(gameClientState))
+ ((Client::GameState*)gameClientState)->Protocol(&protocolData);
+ }
+ break;
case protocol_Lobby_Create:
{
if(dynamic_cast(gameClientState))
{
- GameLogic::Protocol_LobbyCreateGame tp();
int id = p.Get(1).value.netInt;
std::string name = p.Get(19).value.netCharPtr;
Oyster::Math::Float4x4 w;
diff --git a/Code/Game/DanBiasGame/GameClientState/C_Object.cpp b/Code/Game/DanBiasGame/GameClientState/C_Object.cpp
index 840e6267..3f9e08c1 100644
--- a/Code/Game/DanBiasGame/GameClientState/C_Object.cpp
+++ b/Code/Game/DanBiasGame/GameClientState/C_Object.cpp
@@ -1,4 +1,87 @@
#include "C_Object.h"
using namespace DanBias::Client;
+void C_Object::Init(ModelInitData modelInit)
+{
+ position = modelInit.position;
+ rotation = modelInit.rotation;
+ scale = modelInit.scale;
+ id = modelInit.id;
+ model = Oyster::Graphics::API::CreateModel(modelInit.modelPath);
+ model->Visible = modelInit.visible;
+ updateWorld();
+}
+void C_Object::updateWorld()
+{
+ Oyster::Math3D::Float4x4 translation = Oyster::Math3D::TranslationMatrix(this->position);
+ Oyster::Math3D::Float4x4 rot = Oyster::Math3D::RotationMatrix(this->rotation);
+ //Oyster::Math3D::Float4x4 scale = Oyster::Math3D::;
+ Oyster::Math3D::Float4x4 scale = Oyster::Math3D::Matrix::identity;
+ scale.v[0].x = this->scale[0];
+ scale.v[1].y = this->scale[1];
+ scale.v[2].z = this->scale[2];
+ world = translation * rot * scale;
-
+ model->WorldMatrix = world;
+}
+void C_Object::setWorld(Oyster::Math::Float4x4 world)
+{
+ model->WorldMatrix = world;
+}
+Oyster::Math::Float4x4 C_Object::getWorld() const
+{
+ return world;
+}
+void C_Object::setPos(Oyster::Math::Float3 newPos)
+{
+ this->position = newPos;
+ updateWorld();
+}
+void C_Object::addPos(Oyster::Math::Float3 deltaPos)
+{
+ this->position += deltaPos;
+ updateWorld();
+}
+Oyster::Math::Float3 C_Object::getPos() const
+{
+ return this->position;
+}
+void C_Object::setRot(Oyster::Math::Quaternion newRot)
+{
+ this->rotation = newRot;
+ updateWorld();
+}
+void C_Object::addRot(Oyster::Math::Quaternion deltaRot)
+{
+ this->rotation += deltaRot;
+ updateWorld();
+}
+Oyster::Math::Quaternion C_Object::getRotation() const
+{
+ return this->rotation;
+}
+void C_Object::setScale(Oyster::Math::Float3 newScale)
+{
+ this->scale = newScale;
+ updateWorld();
+}
+void C_Object::addScale(Oyster::Math::Float3 deltaScale)
+{
+ this->scale += deltaScale;
+ updateWorld();
+}
+Oyster::Math::Float3 C_Object::getScale() const
+{
+ return this->scale;
+}
+int C_Object::GetId() const
+{
+ return id;
+}
+void C_Object::Render()
+{
+ Oyster::Graphics::API::RenderModel(model);
+}
+void C_Object::Release()
+{
+ Oyster::Graphics::API::DeleteModel(model);
+}
\ No newline at end of file
diff --git a/Code/Game/DanBiasGame/GameClientState/C_Object.h b/Code/Game/DanBiasGame/GameClientState/C_Object.h
index 1b87174b..9c06d2da 100644
--- a/Code/Game/DanBiasGame/GameClientState/C_Object.h
+++ b/Code/Game/DanBiasGame/GameClientState/C_Object.h
@@ -10,21 +10,40 @@ namespace DanBias
{
int id;
std::wstring modelPath;
- Oyster::Math::Float4x4 world;
+ Oyster::Math::Float3 position;
+ Oyster::Math::Quaternion rotation;
+ Oyster::Math::Float3 scale;
bool visible;
};
class C_Object
{
private:
-
+ Oyster::Math::Float4x4 world;
+ Oyster::Math::Float3 position;
+ Oyster::Math::Quaternion rotation;
+ Oyster::Math::Float3 scale;
+ Oyster::Graphics::Model::Model *model;
+ int id;
+ void updateWorld();
public:
- virtual void Init(ModelInitData modelInit) = 0;
- virtual void setPos(Oyster::Math::Float4x4 world) = 0;
+ virtual void Init(ModelInitData modelInit);
+
+ void setWorld(Oyster::Math::Float4x4 world);
+ Oyster::Math::Float4x4 getWorld() const;
+ void setPos(Oyster::Math::Float3 newPos);
+ Oyster::Math::Float3 getPos() const;
+ void addPos(Oyster::Math::Float3 deltaPos);
+ void setRot(Oyster::Math::Quaternion newRot);
+ Oyster::Math::Quaternion getRotation() const;
+ void addRot(Oyster::Math::Quaternion deltaRot);
+ void setScale(Oyster::Math::Float3 newScale);
+ void addScale(Oyster::Math::Float3 deltaScale);
+ Oyster::Math::Float3 getScale() const;
- virtual void Render() = 0;
- virtual void Release() = 0;
- virtual int GetId() = 0;
+ virtual void Render();
+ virtual void Release();
+ virtual int GetId() const;
};};};
#endif
diff --git a/Code/Game/DanBiasGame/GameClientState/C_obj/C_DynamicObj.cpp b/Code/Game/DanBiasGame/GameClientState/C_obj/C_DynamicObj.cpp
index b368b7c4..961ab379 100644
--- a/Code/Game/DanBiasGame/GameClientState/C_obj/C_DynamicObj.cpp
+++ b/Code/Game/DanBiasGame/GameClientState/C_obj/C_DynamicObj.cpp
@@ -1,15 +1,7 @@
#include "C_DynamicObj.h"
#include "DllInterfaces/GFXAPI.h"
using namespace DanBias::Client;
-struct C_DynamicObj::myData
-{
- myData(){}
- Oyster::Graphics::Model::Model *model;
- int ID;
- // light
- // sound
- // effect
-}privData;
+
C_DynamicObj::C_DynamicObj(void)
{
}
@@ -21,28 +13,5 @@ C_DynamicObj::~C_DynamicObj(void)
}
void C_DynamicObj::Init(ModelInitData modelInit)
{
- // load models
- privData = new myData();
- privData->model = Oyster::Graphics::API::CreateModel(modelInit.modelPath);
- privData->model->WorldMatrix = modelInit.world;
- privData->model->Visible = modelInit.visible;
- privData->ID = modelInit.id;
-}
-void C_DynamicObj::setPos(Oyster::Math::Float4x4 world)
-{
- privData->model->WorldMatrix = world;
-}
-
-void C_DynamicObj::Render()
-{
- Oyster::Graphics::API::RenderModel(privData->model);
-}
-void C_DynamicObj::Release()
-{
- Oyster::Graphics::API::DeleteModel(privData->model);
- delete privData;
-}
-int C_DynamicObj::GetId()
-{
- return privData->ID;
+ C_Object::Init(modelInit);
}
\ No newline at end of file
diff --git a/Code/Game/DanBiasGame/GameClientState/C_obj/C_DynamicObj.h b/Code/Game/DanBiasGame/GameClientState/C_obj/C_DynamicObj.h
index ee25a992..ecb874d1 100644
--- a/Code/Game/DanBiasGame/GameClientState/C_obj/C_DynamicObj.h
+++ b/Code/Game/DanBiasGame/GameClientState/C_obj/C_DynamicObj.h
@@ -8,16 +8,10 @@ namespace DanBias
class C_DynamicObj : public C_Object
{
private:
- struct myData;
- myData* privData;
public:
C_DynamicObj(void);
virtual ~C_DynamicObj(void);
void Init(ModelInitData modelInit);
- void setPos(Oyster::Math::Float4x4 world);
- void Render();
- void Release();
- int GetId();
};};};
-#endif
+#endif
\ No newline at end of file
diff --git a/Code/Game/DanBiasGame/GameClientState/C_obj/C_Player.cpp b/Code/Game/DanBiasGame/GameClientState/C_obj/C_Player.cpp
index 1ab43024..d30fcf24 100644
--- a/Code/Game/DanBiasGame/GameClientState/C_obj/C_Player.cpp
+++ b/Code/Game/DanBiasGame/GameClientState/C_obj/C_Player.cpp
@@ -2,20 +2,11 @@
#include "DllInterfaces/GFXAPI.h"
using namespace DanBias::Client;
-struct C_Player::myData
-{
- myData(){}
- Oyster::Math3D::Float4x4 view;
- Oyster::Math3D::Float4x4 proj;
- Oyster::Graphics::Model::Model *model;
- Oyster::Math3D::Float4 lookDir;
- int ID;
-}privData;
-
C_Player::C_Player(void)
+ :C_DynamicObj()
{
-}
+}
C_Player::~C_Player(void)
{
@@ -24,29 +15,5 @@ C_Player::~C_Player(void)
void C_Player::Init(ModelInitData modelInit)
{
- // load models
- privData = new myData();
- privData->model = Oyster::Graphics::API::CreateModel(modelInit.modelPath);
- privData->model->WorldMatrix = modelInit.world;
- privData->model->Visible = modelInit.visible;
- privData->ID = modelInit.id;
- privData->lookDir = Oyster::Math3D::Float4 (0,0,1,0);
-}
-void C_Player::setPos(Oyster::Math::Float4x4 world)
-{
- privData->model->WorldMatrix = world;
-}
-
-void C_Player::Render()
-{
- Oyster::Graphics::API::RenderModel(privData->model);
-}
-void C_Player::Release()
-{
- Oyster::Graphics::API::DeleteModel(privData->model);
- delete privData;
-}
-int C_Player::GetId()
-{
- return privData->ID;
+ C_Object::Init(modelInit);
}
\ No newline at end of file
diff --git a/Code/Game/DanBiasGame/GameClientState/C_obj/C_Player.h b/Code/Game/DanBiasGame/GameClientState/C_obj/C_Player.h
index 794bf51a..9d7c3de0 100644
--- a/Code/Game/DanBiasGame/GameClientState/C_obj/C_Player.h
+++ b/Code/Game/DanBiasGame/GameClientState/C_obj/C_Player.h
@@ -1,26 +1,17 @@
#ifndef DANBIAS_CLIENT_CPLAYER_H
#define DANBIAS_CLIENT_CPLAYER_H
-#include "../C_Object.h"
+#include "C_DynamicObj.h"
namespace DanBias
{
namespace Client
{
-class C_Player : public C_Object
+class C_Player : public C_DynamicObj
{
private:
- struct myData;
- myData* privData;
- //Oyster::Graphics:: LIght
public:
C_Player(void);
- ~C_Player(void);
+ virtual ~C_Player(void);
void Init(ModelInitData modelInit);
- void setPos(Oyster::Math::Float4x4 world);
-
- void Render();
- void Release();
- int GetId();
};};};
#endif
-
diff --git a/Code/Game/DanBiasGame/GameClientState/C_obj/C_StaticObj.cpp b/Code/Game/DanBiasGame/GameClientState/C_obj/C_StaticObj.cpp
index 5e96c239..a61768e4 100644
--- a/Code/Game/DanBiasGame/GameClientState/C_obj/C_StaticObj.cpp
+++ b/Code/Game/DanBiasGame/GameClientState/C_obj/C_StaticObj.cpp
@@ -1,51 +1,16 @@
-
#include "C_StaticObj.h"
#include "DllInterfaces/GFXAPI.h"
using namespace DanBias::Client;
-struct C_StaticObj::myData
-{
- myData(){}
- Oyster::Graphics::Model::Model *model;
- int ID;
- // light
- // sound
- // effect
-}privData;
C_StaticObj::C_StaticObj(void)
{
+
}
-
-
C_StaticObj::~C_StaticObj(void)
{
}
void C_StaticObj::Init(ModelInitData modelInit)
{
- // load models
- privData = new myData();
- privData->model = Oyster::Graphics::API::CreateModel(modelInit.modelPath);
- privData->model->WorldMatrix = modelInit.world;
- privData->model->Visible = modelInit.visible;
- privData->ID = modelInit.id;
-
+ C_Object::Init(modelInit);
}
-void C_StaticObj::setPos(Oyster::Math::Float4x4 world)
-{
- privData->model->WorldMatrix = world;
-}
-
-void C_StaticObj::Render()
-{
- Oyster::Graphics::API::RenderModel(privData->model);
-}
-void C_StaticObj::Release()
-{
- Oyster::Graphics::API::DeleteModel(privData->model);
- delete privData;
-}
-int C_StaticObj::GetId()
-{
- return privData->ID;
-}
\ No newline at end of file
diff --git a/Code/Game/DanBiasGame/GameClientState/C_obj/C_StaticObj.h b/Code/Game/DanBiasGame/GameClientState/C_obj/C_StaticObj.h
index 799c0982..d2bcb2a9 100644
--- a/Code/Game/DanBiasGame/GameClientState/C_obj/C_StaticObj.h
+++ b/Code/Game/DanBiasGame/GameClientState/C_obj/C_StaticObj.h
@@ -8,16 +8,10 @@ namespace DanBias
class C_StaticObj : public C_Object
{
private:
- struct myData;
- myData* privData;
public:
C_StaticObj(void);
virtual ~C_StaticObj(void);
void Init(ModelInitData modelInit);
- void setPos(Oyster::Math::Float4x4 world);
- void Render();
- void Release();
- int GetId();
};};};
#endif
\ No newline at end of file
diff --git a/Code/Game/DanBiasGame/GameClientState/C_obj/C_UIobject.cpp b/Code/Game/DanBiasGame/GameClientState/C_obj/C_UIobject.cpp
index 8df19dc1..5ed3bc36 100644
--- a/Code/Game/DanBiasGame/GameClientState/C_obj/C_UIobject.cpp
+++ b/Code/Game/DanBiasGame/GameClientState/C_obj/C_UIobject.cpp
@@ -2,13 +2,6 @@
#include "DllInterfaces/GFXAPI.h"
using namespace DanBias::Client;
-struct C_UIobject::myData
-{
- myData(){}
- Oyster::Graphics::Model::Model *model;
- int ID;
-}privData;
-
C_UIobject::C_UIobject(void)
{
}
@@ -19,29 +12,5 @@ C_UIobject::~C_UIobject(void)
}
void C_UIobject::Init(ModelInitData modelInit)
{
- // load models
- privData = new myData();
- privData->model = Oyster::Graphics::API::CreateModel(modelInit.modelPath);
- privData->model->WorldMatrix = modelInit.world;
- privData->model->Visible = modelInit.visible;
- privData->ID = modelInit.id;
-
-}
-void C_UIobject::setPos(Oyster::Math::Float4x4 world)
-{
- privData->model->WorldMatrix = world;
-}
-
-void C_UIobject::Render()
-{
- Oyster::Graphics::API::RenderModel(privData->model);
-}
-void C_UIobject::Release()
-{
- Oyster::Graphics::API::DeleteModel(privData->model);
- delete privData;
-}
-int C_UIobject::GetId()
-{
- return privData->ID;
+ C_Object::Init(modelInit);
}
\ No newline at end of file
diff --git a/Code/Game/DanBiasGame/GameClientState/C_obj/C_UIobject.h b/Code/Game/DanBiasGame/GameClientState/C_obj/C_UIobject.h
index b41fb047..f002fcb2 100644
--- a/Code/Game/DanBiasGame/GameClientState/C_obj/C_UIobject.h
+++ b/Code/Game/DanBiasGame/GameClientState/C_obj/C_UIobject.h
@@ -8,16 +8,11 @@ namespace DanBias
class C_UIobject : public C_Object
{
private:
- struct myData;
- myData* privData;
+
public:
C_UIobject(void);
virtual ~C_UIobject(void);
void Init(ModelInitData modelInit);
void setPos(Oyster::Math::Float4x4 world);
-
- void Render();
- void Release();
- int GetId();
};};};
#endif
\ No newline at end of file
diff --git a/Code/Game/DanBiasGame/GameClientState/Camera.cpp b/Code/Game/DanBiasGame/GameClientState/Camera.cpp
index 13b5a70f..afdf2eab 100644
--- a/Code/Game/DanBiasGame/GameClientState/Camera.cpp
+++ b/Code/Game/DanBiasGame/GameClientState/Camera.cpp
@@ -2,7 +2,7 @@
Camera::Camera()
{
- this->m_position = Oyster::Math::Float3(0, 50, 0);
+ this->m_position = Oyster::Math::Float3(0, 600, 0);
this->mRight = Oyster::Math::Float3(1, 0, 0);
this->mUp = Oyster::Math::Float3(0, 1, 0);
this->mLook = Oyster::Math::Float3(0, 0, 1);
diff --git a/Code/Game/DanBiasGame/GameClientState/GameClientState.h b/Code/Game/DanBiasGame/GameClientState/GameClientState.h
index 378eeefc..0545b866 100644
--- a/Code/Game/DanBiasGame/GameClientState/GameClientState.h
+++ b/Code/Game/DanBiasGame/GameClientState/GameClientState.h
@@ -35,6 +35,11 @@ public:
};
struct KeyInput :public ProtocolStruct
{
+ /*
+ * key[0] =
+ *
+ *
+ */
bool key[6];
};
struct PlayerPos :public ProtocolStruct
diff --git a/Code/Game/DanBiasGame/GameClientState/GameState.cpp b/Code/Game/DanBiasGame/GameClientState/GameState.cpp
index 63f9def6..2a9d6746 100644
--- a/Code/Game/DanBiasGame/GameClientState/GameState.cpp
+++ b/Code/Game/DanBiasGame/GameClientState/GameState.cpp
@@ -1,20 +1,17 @@
#include "GameState.h"
#include "DllInterfaces/GFXAPI.h"
-#include "C_obj/C_Player.h"
-#include "C_obj/C_DynamicObj.h"
#include
#include "NetworkClient.h"
#include "Camera.h"
#include
using namespace DanBias::Client;
-
+using namespace Oyster::Math;
struct GameState::myData
{
myData(){}
- Oyster::Math3D::Float4x4 view;
- Oyster::Math3D::Float4x4 proj;
- std::vector object;
+ //std::vector object;
+ int modelCount;
Oyster::Network::NetworkClient* nwClient;
gameStateState state;
@@ -79,126 +76,204 @@ GameState::gameStateState GameState::LoadGame()
plight.Bright = 2.0f;
Oyster::Graphics::API::AddLight(plight);
- LoadModels(L"map");
+ LoadModels();
InitCamera(Oyster::Math::Float3(0.0f,0.0f,20.0f));
+ // hardcoded objects
+ LoadModels();
+ Float3 startPos = Float3(0,0,20.0f);
+ InitCamera(startPos);
return gameStateState_playing;
}
-bool GameState::LoadModels(std::wstring mapFile)
+bool GameState::LoadModels()
{
// open file
// read file
// init models
- int nrOfBoxex = 20;
+ int nrOfBoxex = 5;
int id = 100;
-
-// add world model
+
+ // add world model
ModelInitData modelData;
- Oyster::Math3D::Float4x4 translate;
- C_Object* obj;
- translate = Oyster::Math3D::TranslationMatrix(Oyster::Math::Float3(0,0,0));
- modelData.world = translate ;//modelData.world * translate
+
+ modelData.position = Oyster::Math::Float3(0,0,0);
+ modelData.rotation = Oyster::Math::Quaternion::identity;
+ modelData.scale = Oyster::Math::Float3(2,2,2);
+
modelData.modelPath = L"world_earth.dan";
modelData.id = id++;
- obj = new C_Player();
- privData->object.push_back(obj);
- privData->object[privData->object.size() -1 ]->Init(modelData);
+ this->staticObjects.Push(new C_StaticObj());
+ this->staticObjects[this->staticObjects.Size() -1 ]->Init(modelData);
-/*
-// add box model
- modelData.world = Oyster::Math3D::Float4x4::identity;
+ /*
+ // add box model
+ modelData.position = Oyster::Math::Float3(0,0,0);
+ modelData.rotation = Oyster::Math::Quaternion::identity;
+ modelData.scale = Oyster::Math::Float3(1,1,1);
modelData.modelPath = L"crate_colonists.dan";
-
+
for(int i =0; i< nrOfBoxex; i ++)
{
- translate = Oyster::Math3D::TranslationMatrix(Oyster::Math::Float3(4,320,0));
- modelData.world = modelData.world * translate;
+ modelData.position = Oyster::Math::Float3(4,320,0);
modelData.id = id++;
- obj = new C_Player();
- privData->object.push_back(obj);
- privData->object[privData->object.size() -1 ]->Init(modelData);
- modelData.world = Oyster::Math3D::Float4x4::identity;
+ this->dynamicObjects.Push(new C_DynamicObj());
+ this->dynamicObjects[this->dynamicObjects.Size() -1 ]->Init(modelData);
}
-// add crystal model
- modelData.world = Oyster::Math3D::Float4x4::identity;
- translate = Oyster::Math3D::TranslationMatrix(Oyster::Math::Float3(10, 301, 0));
-
- modelData.world = modelData.world * translate;
- modelData.visible = true;
+
+ // add crystal model
+ modelData.position = Oyster::Math::Float3(10, 301, 0);
modelData.modelPath = L"crystalformation_b.dan";
modelData.id = id++;
// load models
- obj = new C_Player();
- privData->object.push_back(obj);
- privData->object[privData->object.size() -1 ]->Init(modelData);
+ this->dynamicObjects.Push(new C_DynamicObj());
+ this->dynamicObjects[this->dynamicObjects.Size() -1 ]->Init(modelData);
+
+ // add house model
+ modelData.position = Oyster::Math::Float3(-50, 290, 0);
+ //Oyster::Math3D::Float4x4 rot = Oyster::Math3D::RotationMatrix(Oyster::Math::Float3(0 ,Utility::Value::Radian(90.0f), 0));
-// add house model
- modelData.world = Oyster::Math3D::Float4x4::identity;
- translate = Oyster::Math3D::TranslationMatrix(Oyster::Math::Float3(-50, 290, 0));
- Oyster::Math3D::Float4x4 rot = Oyster::Math3D::RotationMatrix(Oyster::Math::Float3(0 ,Utility::Value::Radian(90.0f), 0));
-
- modelData.world = modelData.world * translate * rot;
modelData.visible = true;
modelData.modelPath = L"building_corporation.dan";
modelData.id = id++;
// load models
- obj = new C_Player();
- privData->object.push_back(obj);
- privData->object[privData->object.size() -1 ]->Init(modelData);
+ this->dynamicObjects.Push(new C_DynamicObj());
+ this->dynamicObjects[this->dynamicObjects.Size() -1 ]->Init(modelData);
+ // add player model
+ modelData.position = Oyster::Math::Float3(0, 320, 0);
+ modelData.modelPath = L"char_still_sizeref.dan";
+ modelData.id = id++;
+ // load models
+ this->dynamicObjects.Push(new C_DynamicObj());
+ this->dynamicObjects[this->dynamicObjects.Size() -1 ]->Init(modelData);
+
+ // add player model 2
+ modelData.position = Oyster::Math::Float3(50, 320, 0);
+ modelData.modelPath = L"char_still_sizeref.dan";
+ modelData.id = id++;
+ // load models
+ this->dynamicObjects.Push(new C_DynamicObj());
+ this->dynamicObjects[this->dynamicObjects.Size() -1 ]->Init(modelData);
+
// add jumppad
- modelData.world = Oyster::Math3D::Float4x4::identity;
- translate = Oyster::Math3D::TranslationMatrix(Oyster::Math::Float3(4, 300.3, 0));
- //Oyster::Math3D::RotationMatrix_AxisZ()
- modelData.world = modelData.world * translate;
- modelData.visible = true;
+ modelData.position = Oyster::Math::Float3(4, 300.3, 0);
modelData.modelPath = L"jumppad_round.dan";
modelData.id = id++;
// load models
- obj = new C_Player();
- privData->object.push_back(obj);
- privData->object[privData->object.size() -1 ]->Init(modelData);
+ this->dynamicObjects.Push(new C_DynamicObj());
+ this->dynamicObjects[this->dynamicObjects.Size() -1 ]->Init(modelData);
// add sky sphere
- modelData.world = Oyster::Math3D::Float4x4::identity;
- translate = Oyster::Math3D::TranslationMatrix(Oyster::Math::Float3(0, 0, 0));
- //Oyster::Math3D::RotationMatrix_AxisZ()
- modelData.world = modelData.world * translate;
- modelData.world.v[0].x = 800;
- modelData.world.v[1].y = 800;
- modelData.world.v[2].z = 800;
- modelData.visible = true;
+ modelData.position = Oyster::Math::Float3(0,0,0);
+ modelData.scale = Oyster::Math::Float3(800,800,800);
modelData.modelPath = L"skysphere.dan";
modelData.id = id++;
// load models
- obj = new C_Player();
- privData->object.push_back(obj);
- privData->object[privData->object.size() -1 ]->Init(modelData);
-
- */
+ this->dynamicObjects.Push(new C_DynamicObj());
+ this->dynamicObjects[this->dynamicObjects.Size() -1 ]->Init(modelData);*/
return true;
}
-bool GameState::InitCamera(Oyster::Math::Float3 startPos)
+bool GameState::LoadModels(std::string mapFile)
{
- Oyster::Math::Float3 dir = Oyster::Math::Float3(0,0,1);
- Oyster::Math::Float3 up =Oyster::Math::Float3(0,1,0);
- Oyster::Math::Float3 pos = Oyster::Math::Float3(0, 0, 20);
+ GameLogic::LevelLoader levelLoader;
+ std::vector> objects;
+ objects = levelLoader.LoadLevel(mapFile);
+ int objCount = objects.size();
+ int modelId = 0;
+ ModelInitData modelData;
+ for (int i = 0; i < objCount; i++)
+ {
+ GameLogic::ObjectTypeHeader* obj = objects.at(i);
+
+ switch (obj->typeID)
+ {
+ case GameLogic::ObjectType::ObjectType_LevelMetaData:
+
+ break;
+ case GameLogic::ObjectType::ObjectType_Static:
+ {
+ GameLogic::ObjectHeader* staticObjData = ((GameLogic::ObjectHeader*)obj);
+
+ modelData.modelPath.assign(staticObjData->ModelFile.begin(), staticObjData->ModelFile.end());
+ modelData.visible = true;
+ //modelData.position = ;
+ //modelData.rotation = Oyster::Math::Quaternion(Oyster::Math::Float3(2,2,-2), 1);
+ //modelData.scale = Oyster::Math::Float3(2,2,2);
+ modelData.id = modelId++;
+
+ this->staticObjects.Push(new C_StaticObj());
+ this->staticObjects[this->staticObjects.Size() -1 ]->Init(modelData);
+ }
+ break;
+ case GameLogic::ObjectType::ObjectType_Dynamic:
+ {
+ GameLogic::ObjectHeader* dynamicObjData = ((GameLogic::ObjectHeader*)obj);
+ //modelData.position = ;
+ //modelData.rotation = Oyster::Math::Quaternion(Oyster::Math::Float3(2,2,-2), 1);
+ //modelData.scale = Oyster::Math::Float3(2,2,2);
+ modelData.modelPath.assign(dynamicObjData->ModelFile.begin(), dynamicObjData->ModelFile.end());
+ modelData.visible = true;
+ modelData.id = modelId++;
+
+ this->dynamicObjects.Push(new C_DynamicObj());
+ this->dynamicObjects[this->dynamicObjects.Size() -1 ]->Init(modelData);
+ }
+ break;
+ case GameLogic::ObjectType::ObjectType_Light:
+ {
+ GameLogic::BasicLight* lightData = ((GameLogic::BasicLight*)obj);
+
+ if(lightData->lightType == GameLogic::LightType_PointLight)
+ {
+ Oyster::Graphics::Definitions::Pointlight plight;
+ plight.Pos = ((GameLogic::PointLight*)lightData)->position;
+ plight.Color = lightData->diffuseColor;
+ plight.Radius = 100;
+ plight.Bright = 0.9f;
+ Oyster::Graphics::API::AddLight(plight);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ myId += modelId++;
+ // add player model
+ //modelData.position = ;
+ //modelData.rotation = Oyster::Math::Quaternion(Oyster::Math::Float3(2,2,-2), 1);
+ //modelData.scale = Oyster::Math::Float3(2,2,2);
+
+
+ modelData.visible = true;
+ modelData.modelPath = L"char_still_sizeref.dan";
+ modelData.id = myId;
+ // load models
+ this->dynamicObjects.Push(new C_DynamicObj());
+ this->dynamicObjects[this->dynamicObjects.Size() -1 ]->Init(modelData);
+
+ /*C_Player* obj = new C_Player();
+ privData->object.push_back(obj);
+ privData->object[privData->object.size() -1 ]->Init(modelData);
+ */
+ return true;
+
+}
+bool GameState::InitCamera(Float3 startPos)
+{
+ Float3 dir = Float3(0,0,1);
+ Float3 up = Float3(0,1,0);
+ Float3 pos = Float3(0, 0, 20);
camera->LookAt(pos, dir, up);
- camera->SetLens(3.14f/2, 1024/768, 1, 1000);
-
- privData->proj = Oyster::Math3D::ProjectionMatrix_Perspective(Oyster::Math::pi / 4, 1024.0f / 768.0f, .1f,1000);
- //privData->proj = Oyster::Math3D::ProjectionMatrix_Orthographic(1024, 768, 1, 1000);
- Oyster::Graphics::API::SetProjection(privData->proj);
+ camera->SetLens(pi/4, 1024/768, 1, 1000);
camera->UpdateViewMatrix();
- privData->view = camera->View();
- privData->view = Oyster::Math3D::ViewMatrix_LookAtDirection(Oyster::Math::Float3(0,0,-1),Oyster::Math::Float3(0,1,0),startPos);
- privData->view = Oyster::Math3D::OrientationMatrix_LookAtDirection(Oyster::Math::Float3(0,0,-1),Oyster::Math::Float3(0,1,0),startPos);
- privData->view = Oyster::Math3D::InverseOrientationMatrix(privData->view);
+ Oyster::Graphics::API::SetProjection(camera->Proj());
+
return true;
}
void GameState::InitiatePlayer(int id, std::wstring modelName, Oyster::Math::Float4x4 world)
@@ -208,15 +283,18 @@ void GameState::InitiatePlayer(int id, std::wstring modelName, Oyster::Math::Flo
ModelInitData modelData;
C_Object* obj;
modelData.visible = true;
- modelData.world = world;
+ //modelData.world = world;
+ modelData.position = Oyster::Math::Float3(world[12], world[13], world[14]);
+ modelData.rotation = Oyster::Math::Quaternion(Oyster::Math::Float3(0,0,0), 1);
+ modelData.scale = Oyster::Math::Float3(1,1,1);
modelData.modelPath = modelName;
modelData.id = myId;
obj = new C_Player();
- privData->object.push_back(obj);
- privData->object[privData->object.size() -1 ]->Init(modelData);
+ this->dynamicObjects.Push(obj);
+ this->dynamicObjects[this->dynamicObjects.Size() -1 ]->Init(modelData);
- //printf("Move message recieved!");
+
Oyster::Math::Float3 right = Oyster::Math::Float3(world[0], world[1], world[2]);
Oyster::Math::Float3 up = Oyster::Math::Float3(world[4], world[5], world[6]);
Oyster::Math::Float3 objForward = (Oyster::Math::Float3(world[8], world[9], world[10]));
@@ -238,7 +316,7 @@ void GameState::InitiatePlayer(int id, std::wstring modelName, Oyster::Math::Flo
camera->setLook(objForward);
up *= 2;
- objForward *= -3;
+ objForward *= 3;
Oyster::Math::Float3 cameraPos = up + pos + objForward;
camera->SetPosition(cameraPos);
@@ -282,25 +360,28 @@ GameClientState::ClientState GameState::Update(float deltaTime, InputClass* KeyI
bool GameState::Render()
{
Oyster::Graphics::API::SetView(camera->View());
- //Oyster::Graphics::API::SetProjection(camera->Proj());
- //Oyster::Graphics::API::SetView(privData->view);
- Oyster::Graphics::API::SetProjection(privData->proj);
+
Oyster::Graphics::API::NewFrame();
- for (unsigned int i = 0; i < privData->object.size(); i++)
+ for (unsigned int i = 0; i < staticObjects.Size(); i++)
{
- privData->object[i]->Render();
+ staticObjects[i]->Render();
}
+ for (unsigned int i = 0; i < dynamicObjects.Size(); i++)
+ {
+ dynamicObjects[i]->Render();
+ }
+
Oyster::Graphics::API::EndFrame();
return true;
}
bool GameState::Release()
{
- for (unsigned int i = 0; i < privData->object.size(); i++)
+ /*for (unsigned int i = 0; i < privData->object.size(); i++)
{
- privData->object[i]->Release();
- delete privData->object[i];
- privData->object[i] = NULL;
- }
+ privData->object[i]->Release();
+ delete privData->object[i];
+ privData->object[i] = NULL;
+ }*/
delete privData;
privData = NULL;
@@ -309,20 +390,11 @@ bool GameState::Release()
void GameState::readKeyInput(InputClass* KeyInput)
{
- bool send = false;
- GameLogic::Protocol_PlayerMovement movePlayer;
- movePlayer.bForward = false;
- movePlayer.bBackward = false;
- movePlayer.bLeft = false;
- movePlayer.bRight = false;
-
if(KeyInput->IsKeyPressed(DIK_W))
{
-
if(!key_forward)
{
- movePlayer.bForward = true;
- send = true;
+ privData->nwClient->Send(GameLogic::Protocol_PlayerMovementForward());
key_forward = true;
}
}
@@ -333,8 +405,7 @@ void GameState::readKeyInput(InputClass* KeyInput)
{
if(!key_backward)
{
- movePlayer.bBackward = true;
- send = true;
+ privData->nwClient->Send(GameLogic::Protocol_PlayerMovementBackward());
key_backward = true;
}
}
@@ -345,8 +416,7 @@ void GameState::readKeyInput(InputClass* KeyInput)
{
if(!key_strafeLeft)
{
- movePlayer.bLeft = true;
- send = true;
+ privData->nwClient->Send(GameLogic::Protocol_PlayerMovementLeft());
key_strafeLeft = true;
}
}
@@ -357,8 +427,7 @@ void GameState::readKeyInput(InputClass* KeyInput)
{
if(!key_strafeRight)
{
- movePlayer.bRight = true;
- send = true;
+ privData->nwClient->Send(GameLogic::Protocol_PlayerMovementRight());
key_strafeRight = true;
}
}
@@ -366,13 +435,8 @@ void GameState::readKeyInput(InputClass* KeyInput)
key_strafeRight = false;
- if (privData->nwClient->IsConnected() && send)
- {
- privData->nwClient->Send(movePlayer);
- }
-
//send delta mouse movement
- if (KeyInput->IsMousePressed())
+ //if (KeyInput->IsMousePressed())
{
camera->Yaw(-KeyInput->GetYaw());
camera->Pitch(KeyInput->GetPitch());
@@ -437,9 +501,7 @@ void GameState::readKeyInput(InputClass* KeyInput)
{
if(!key_Jump)
{
- GameLogic::Protocol_PlayerJump playerJump;
- playerJump.hasJumped = true;
- privData->nwClient->Send(playerJump);
+ privData->nwClient->Send(GameLogic::Protocol_PlayerJump());
key_Jump = true;
}
}
@@ -459,13 +521,17 @@ void GameState::Protocol(ProtocolStruct* pos)
void GameState::Protocol( PlayerPos* pos )
{
- Oyster::Math::Float4x4 world, translate;
+ //Oyster::Math::Float4x4 world, translate;
- world = Oyster::Math::Float4x4::identity;
- translate = Oyster::Math::Float4x4::identity;
- translate = Oyster::Math3D::TranslationMatrix(Oyster::Math::Float3(pos->playerPos[0],pos->playerPos[1],pos->playerPos[2]));
- world = world * translate;
- privData->object[0]->setPos( world );
+ //world = Oyster::Math::Float4x4::identity;
+ //translate = Oyster::Math::Float4x4::identity;
+ //translate = Oyster::Math3D::TranslationMatrix(Oyster::Math::Float3(pos->playerPos[0],pos->playerPos[1],pos->playerPos[2]));
+ //world = world * translate;
+ ////privData->object[0]->setPos( world );
+ //for (unsigned int i = 0; i < dynamicObjects.Size(); i++)
+ //{
+ // dynamicObjects[i]->Render();
+ //}
}
void GameState::Protocol( ObjPos* pos )
@@ -476,22 +542,24 @@ void GameState::Protocol( ObjPos* pos )
world[i] = pos->worldPos[i];
}
//printf("pos for obj %d, ",pos->object_ID );
- for (unsigned int i = 0; i < privData->object.size(); i++)
+ for (unsigned int i = 0; i < dynamicObjects.Size(); i++)
{
- if(privData->object[i]->GetId() == pos->object_ID)
+ if(dynamicObjects[i]->GetId() == pos->object_ID)
{
- privData->object[i]->setPos(world);
- if(pos->object_ID == myId) // playerobj
+
+ //dynamicObjects[i]->setPos(Float3(world[12], world[13], world[14]));
+ dynamicObjects[i]->setWorld(world);
+
+ if(dynamicObjects[i]->GetId() == myId) // playerobj
{
- //printf("Move message recieved!");
- Oyster::Math::Float3 right = Oyster::Math::Float3(world[0], world[1], world[2]);
- Oyster::Math::Float3 up = Oyster::Math::Float3(world[4], world[5], world[6]);
- Oyster::Math::Float3 objForward = (Oyster::Math::Float3(world[8], world[9], world[10]));
- Oyster::Math::Float3 pos = Oyster::Math::Float3(world[12], world[13], world[14]);
+ Float3 right = Float3(world[0], world[1], world[2]);
+ Float3 up = Float3(world[4], world[5], world[6]);
+ Float3 objForward = Float3(world[8], world[9], world[10]);
+ Float3 pos = Float3(world[12], world[13], world[14]);
- Oyster::Math::Float3 cameraLook = camera->GetLook();
- Oyster::Math::Float3 cameraUp = camera->GetUp();
+ Float3 cameraLook = camera->GetLook();
+ Float3 cameraUp = camera->GetUp();
@@ -501,16 +569,16 @@ void GameState::Protocol( ObjPos* pos )
Oyster::Math::Float3 newLook = up.Cross(right);
newLook.Normalize();*/
- camera->setRight(right);
- camera->setUp(up);
- camera->setLook(objForward);
+ //camera->setRight(right);
+ //camera->setUp(up);
+ //camera->setLook(objForward);
up *= 1;
objForward *= -2;
- Oyster::Math::Float3 cameraPos = up + pos + objForward;
- camera->SetPosition(cameraPos);
-
- camera->UpdateViewMatrix();
+ Oyster::Math::Float3 cameraPos = pos + up + objForward;
+ //camera->SetPosition(cameraPos);
+ //camera->UpdateViewMatrix();
+
}
}
}
@@ -526,28 +594,29 @@ void GameState::Protocol( NewObj* newObj )
}
ModelInitData modelData;
- modelData.world = world;
+ //modelData.world = world;
modelData.visible = true;
modelData.id = newObj->object_ID;
//not sure if this is good parsing rom char* to wstring
const char* path = newObj->path;
modelData.modelPath = std::wstring(path, path + strlen(path));
// load models
- C_Object* player = new C_Player();
+ C_DynamicObj* player = new C_DynamicObj();
player->Init(modelData);
- privData->object.push_back(player);
+ dynamicObjects.Push(player);
}
void DanBias::Client::GameState::Protocol( RemoveObj* obj )
{
- for (unsigned int i = 0; i < privData->object.size(); i++)
+ for (unsigned int i = 0; i < dynamicObjects.Size(); i++)
{
- if(privData->object[i]->GetId() == obj->object_ID)
+ if(dynamicObjects[i]->GetId() == obj->object_ID)
{
- privData->object.at(i)->Release();
- privData->object.erase(privData->object.begin() + i );
+ //dynamicObjects[i]->Release();
+ dynamicObjects[i].Release();
+ //dynamicObjects.erase(privData->object.begin() + i );
}
}
//privData->object[obj->object_ID]->Release( );
diff --git a/Code/Game/DanBiasGame/GameClientState/GameState.h b/Code/Game/DanBiasGame/GameClientState/GameState.h
index 2cff9ed9..3f182b2a 100644
--- a/Code/Game/DanBiasGame/GameClientState/GameState.h
+++ b/Code/Game/DanBiasGame/GameClientState/GameState.h
@@ -4,6 +4,11 @@
#include "OysterMath.h"
#include
#include "Camera.h"
+#include "LevelLoader/LevelLoader.h"
+#include "C_obj/C_Player.h"
+#include "C_obj/C_DynamicObj.h"
+#include "C_obj/C_StaticObj.h"
+#include "DynamicArray.h"
namespace DanBias
{
namespace Client
@@ -30,12 +35,16 @@ private:
float pitch;
struct myData;
myData* privData;
+ Utility::DynamicMemory::DynamicArray> staticObjects;
+ Utility::DynamicMemory::DynamicArray> dynamicObjects;
+ //Utility::DynamicMemory::DynamicArray> playObjects;
public:
GameState(void);
~GameState(void);
bool Init(Oyster::Network::NetworkClient* nwClient);
GameClientState::ClientState Update(float deltaTime, InputClass* KeyInput) override;
- bool LoadModels(std::wstring mapFile) ;
+ bool LoadModels(std::string mapFile);
+ bool LoadModels();
bool InitCamera(Oyster::Math::Float3 startPos) ;
void InitiatePlayer(int id, std::wstring modelName, Oyster::Math::Float4x4 world);
gameStateState LoadGame();
diff --git a/Code/Game/DanBiasGame/GameClientState/LanMenuState.cpp b/Code/Game/DanBiasGame/GameClientState/LanMenuState.cpp
index 8df39bfa..092307af 100644
--- a/Code/Game/DanBiasGame/GameClientState/LanMenuState.cpp
+++ b/Code/Game/DanBiasGame/GameClientState/LanMenuState.cpp
@@ -64,15 +64,16 @@ bool LanMenuState::LoadModels(std::wstring file)
ModelInitData modelData;
- modelData.world = Oyster::Math3D::Float4x4::identity;
+ modelData.position = Oyster::Math::Float3(0,0,0);
+ modelData.rotation = Oyster::Math::Quaternion::identity;
+ modelData.scale = Oyster::Math::Float3(1,1,1);
modelData.visible = true;
modelData.modelPath = L"..\\Content\\Models\\box_2.dan";
// load models
privData->object[0] = new C_StaticObj();
privData->object[0]->Init(modelData);
- Oyster::Math3D::Float4x4 translate = Oyster::Math3D::TranslationMatrix(Oyster::Math::Float3(-2,-2,-2));
- modelData.world = modelData.world * translate;
+ modelData.position = Oyster::Math::Float3(-2, -2, -2);
privData->object[1] = new C_DynamicObj();
privData->object[1]->Init(modelData);
diff --git a/Code/Game/DanBiasGame/GameClientState/LevelLoader/LevelLoader.cpp b/Code/Game/DanBiasGame/GameClientState/LevelLoader/LevelLoader.cpp
new file mode 100644
index 00000000..55a39725
--- /dev/null
+++ b/Code/Game/DanBiasGame/GameClientState/LevelLoader/LevelLoader.cpp
@@ -0,0 +1,35 @@
+//////////////////////////////////
+// Created by Sam Svensson 2013 //
+//////////////////////////////////
+
+#include "LevelLoader.h"
+#include "LevelParser.h"
+
+using namespace GameLogic;
+using namespace GameLogic::LevelFileLoader;
+
+struct LevelLoader::PrivData
+{
+ LevelParser parser;
+ std::string folderPath;
+};
+
+LevelLoader::LevelLoader()
+ : pData(new PrivData)
+{
+ pData->folderPath = "Standard path";
+}
+
+LevelLoader::~LevelLoader()
+{
+}
+
+std::vector> LevelLoader::LoadLevel(std::string fileName)
+{
+ return pData->parser.Parse(fileName);
+}
+
+LevelMetaData LevelLoader::LoadLevelHeader(std::string fileName)
+{
+ return pData->parser.ParseHeader(fileName);
+}
\ No newline at end of file
diff --git a/Code/Game/DanBiasGame/GameClientState/LevelLoader/LevelLoader.h b/Code/Game/DanBiasGame/GameClientState/LevelLoader/LevelLoader.h
new file mode 100644
index 00000000..bcd6e587
--- /dev/null
+++ b/Code/Game/DanBiasGame/GameClientState/LevelLoader/LevelLoader.h
@@ -0,0 +1,42 @@
+//////////////////////////////////
+// Created by Sam Svensson 2013 //
+//////////////////////////////////
+
+#ifndef LEVELLOADER_H
+#define LEVELLOADER_H
+
+#include
+#include
+#include "../Misc/Utilities.h"
+#include "ObjectDefines.h"
+
+namespace GameLogic
+{
+ class LevelLoader
+ {
+
+ public:
+ LevelLoader();
+ ~LevelLoader();
+
+ /********************************************************
+ * Loads the level and objects from file.
+ * @param fileName: Path to the level-file that you want to load.
+ * @return: Returns all structs with objects and information about the level.
+ ********************************************************/
+ std::vector> LoadLevel(std::string fileName);
+
+ /********************************************************
+ * Just for fast access for the meta information about the level.
+ * @param fileName: Path to the level-file that you want to load.
+ * @return: Returns the meta information about the level.
+ ********************************************************/
+ LevelMetaData LoadLevelHeader(std::string fileName); //.
+
+ private:
+ struct PrivData;
+ Utility::DynamicMemory::SmartPointer pData;
+ };
+}
+
+#endif
\ No newline at end of file
diff --git a/Code/Game/DanBiasGame/GameClientState/LevelLoader/LevelParser.cpp b/Code/Game/DanBiasGame/GameClientState/LevelLoader/LevelParser.cpp
new file mode 100644
index 00000000..088c3916
--- /dev/null
+++ b/Code/Game/DanBiasGame/GameClientState/LevelLoader/LevelParser.cpp
@@ -0,0 +1,190 @@
+#include "LevelParser.h"
+
+#include "Loader.h"
+#include "ParseFunctions.h"
+
+using namespace GameLogic;
+using namespace ::LevelFileLoader;
+using namespace Utility::DynamicMemory;
+
+LevelParser::LevelParser()
+{
+ formatVersion.formatVersionMajor = 1;
+ formatVersion.formatVersionMinor = 0;
+}
+
+LevelParser::~LevelParser()
+{
+}
+
+std::vector> LevelParser::Parse(std::string filename)
+{
+ int bufferSize = 0;
+ int counter = 0;
+
+ std::vector> objects;
+
+ //Read entire level file.
+ Loader loader;
+ char* buffer = (char*)loader.LoadFile(filename.c_str(), bufferSize);
+
+ //Read format version
+ FormatVersion levelFormatVersion;
+ ParseObject(&buffer[counter], &levelFormatVersion, sizeof(levelFormatVersion));
+ counter += sizeof(levelFormatVersion);
+ if(this->formatVersion != levelFormatVersion)
+ {
+ //Do something if it's not the same version
+ }
+
+ while(counter < bufferSize)
+ {
+ //Get typeID
+ ObjectTypeHeader typeID;
+ ParseObject(&buffer[counter], &typeID, sizeof(typeID));
+ switch((int)typeID.typeID)
+ {
+ case ObjectType_LevelMetaData:
+ {
+ LevelMetaData* header = new LevelMetaData;
+ ParseLevelMetaData(&buffer[counter], *header, counter);
+ objects.push_back(header);
+ break;
+ }
+
+ //This is by design, static and dynamic is using the same converter. Do not add anything inbetween them.
+ case ObjectType_Static: case ObjectType_Dynamic:
+ {
+ ObjectHeader* header = new ObjectHeader;
+ ParseObject(&buffer[counter], *header, counter);
+ objects.push_back(header);
+ break;
+ }
+
+ case ObjectType_Light:
+ {
+ LightType lightType;
+
+ //Get Light type
+ ParseObject(&buffer[counter+4], &lightType, sizeof(lightType));
+
+ switch(lightType)
+ {
+ case LightType_PointLight:
+ {
+ PointLight* header = new PointLight;
+ ParseObject(&buffer[counter], header, sizeof(*header));
+ counter += sizeof(*header);
+ objects.push_back(header);
+ break;
+ }
+ case LightType_DirectionalLight:
+ {
+ DirectionalLight* header = new DirectionalLight;
+ ParseObject(&buffer[counter], header, sizeof(*header));
+ counter += sizeof(*header);
+ objects.push_back(header);
+ break;
+ }
+ case LightType_SpotLight:
+ {
+ SpotLight* header = new SpotLight;
+ ParseObject(&buffer[counter], header, sizeof(*header));
+ counter += sizeof(*header);
+ objects.push_back(header);
+ break;
+ }
+ default:
+ //Undefined LightType.
+ break;
+ }
+ break;
+ }
+ default:
+ //Couldn't find typeID. FAIL!!!!!!
+ break;
+ }
+ }
+
+ return objects;
+}
+
+//för meta information om leveln.
+LevelMetaData LevelParser::ParseHeader(std::string filename)
+{
+ int bufferSize = 0;
+ int counter = 0;
+
+ LevelMetaData levelHeader;
+ levelHeader.typeID = ObjectType::ObjectType_Unknown;
+
+ //Read entire level file.
+ Loader loader;
+ char* buffer = (char*)loader.LoadFile(filename.c_str(), bufferSize);
+
+ //Read format version
+ FormatVersion levelFormatVersion;
+ ParseObject(&buffer[counter], &levelFormatVersion, sizeof(formatVersion));
+ counter += sizeof(levelFormatVersion);
+ if(this->formatVersion != levelFormatVersion)
+ {
+ //Do something if it's not the same version
+ }
+
+ //Find the header in the returned string.
+ while(counter < bufferSize)
+ {
+ ObjectTypeHeader typeID;
+ ParseObject(&buffer[counter], &typeID, sizeof(typeID));
+
+ switch(typeID.typeID)
+ {
+ case ObjectType_LevelMetaData:
+ ParseLevelMetaData(&buffer[counter], levelHeader, counter);
+ return levelHeader;
+ break;
+
+ //This is by design, static and dynamic is using the same converter. Do not add anything inbetween them.
+ case ObjectType_Static: case ObjectType_Dynamic:
+ {
+ ObjectHeader header;
+ ParseObject(&buffer[counter], header, counter);
+ break;
+ }
+
+ case ObjectType_Light:
+ {
+ LightType lightType;
+ ParseObject(&buffer[counter+4], &lightType, sizeof(lightType));
+
+ switch(lightType)
+ {
+ case LightType_PointLight:
+ {
+ counter += sizeof(PointLight);
+ break;
+ }
+ case LightType_DirectionalLight:
+ {
+ counter += sizeof(DirectionalLight);
+ break;
+ }
+ case LightType_SpotLight:
+ {
+ counter += sizeof(SpotLight);
+ break;
+ }
+ default:
+ //Undefined LightType.
+ break;
+ }
+ }
+
+ default:
+ //Couldn't find typeID. FAIL!!!!!!
+ break;
+ }
+ }
+
+ return levelHeader;
+}
\ No newline at end of file
diff --git a/Code/Game/DanBiasGame/GameClientState/LevelLoader/LevelParser.h b/Code/Game/DanBiasGame/GameClientState/LevelLoader/LevelParser.h
new file mode 100644
index 00000000..9ad30642
--- /dev/null
+++ b/Code/Game/DanBiasGame/GameClientState/LevelLoader/LevelParser.h
@@ -0,0 +1,31 @@
+#ifndef LEVEL_PARSER_H
+#define LEVEL_PARSER_H
+
+#include
+#include
+#include "ObjectDefines.h"
+#include "../Misc/Utilities.h"
+
+namespace GameLogic
+{
+ namespace LevelFileLoader
+ {
+ class LevelParser
+ {
+ public:
+ LevelParser();
+ ~LevelParser();
+
+ //
+ std::vector> Parse(std::string filename);
+
+ //
+ LevelMetaData ParseHeader(std::string filename);
+
+ private:
+ FormatVersion formatVersion;
+
+ };
+ }
+}
+#endif
\ No newline at end of file
diff --git a/Code/Game/DanBiasGame/GameClientState/LevelLoader/Loader.cpp b/Code/Game/DanBiasGame/GameClientState/LevelLoader/Loader.cpp
new file mode 100644
index 00000000..3e15315c
--- /dev/null
+++ b/Code/Game/DanBiasGame/GameClientState/LevelLoader/Loader.cpp
@@ -0,0 +1,22 @@
+//////////////////////////////////
+// Created by Sam Svensson 2013 //
+//////////////////////////////////
+
+#include "Loader.h"
+#include
+
+using namespace GameLogic::LevelFileLoader;
+using namespace Oyster::Resource;
+using namespace std;
+
+char* Loader::LoadFile(std::string fileName, int &size)
+{
+ //convert from string to wstring
+ std::wstring temp(fileName.begin(), fileName.end());
+
+ //convert from wstring to wchar then loads the file
+ char* buffer = (char*)OysterResource::LoadResource(temp.c_str(), Oyster::Resource::ResourceType::ResourceType_Byte_Raw, -1 , false);
+
+ size = OysterResource::GetResourceSize(buffer);
+ return buffer;
+}
\ No newline at end of file
diff --git a/Code/Game/DanBiasGame/GameClientState/LevelLoader/Loader.h b/Code/Game/DanBiasGame/GameClientState/LevelLoader/Loader.h
new file mode 100644
index 00000000..198c2a87
--- /dev/null
+++ b/Code/Game/DanBiasGame/GameClientState/LevelLoader/Loader.h
@@ -0,0 +1,28 @@
+//////////////////////////////////
+// Created by Sam Svensson 2013 //
+//////////////////////////////////
+
+#ifndef LOADER_H
+#define LOADER_H
+
+#include "..\Misc\Resource\OysterResource.h"
+#include
+
+namespace GameLogic
+{
+ namespace LevelFileLoader
+ {
+ class Loader
+ {
+ public:
+ Loader (){};
+ ~Loader(){};
+ char* LoadFile(std::string fileName, int &size);
+
+ //TODO:
+ //Add functionality to load physicsObjects (hitboxes)
+ };
+ }
+}
+
+#endif;
\ No newline at end of file
diff --git a/Code/Game/DanBiasGame/GameClientState/LevelLoader/ObjectDefines.h b/Code/Game/DanBiasGame/GameClientState/LevelLoader/ObjectDefines.h
new file mode 100644
index 00000000..8287dafb
--- /dev/null
+++ b/Code/Game/DanBiasGame/GameClientState/LevelLoader/ObjectDefines.h
@@ -0,0 +1,172 @@
+#ifndef OBJECT_DEFINES_H
+#define OBJECT_DEFINES_H
+
+#include
+#include
+
+namespace GameLogic
+{
+ /************************************
+ Enums
+ *************************************/
+
+ enum ObjectType
+ {
+ ObjectType_LevelMetaData,
+ ObjectType_Static,
+ ObjectType_Dynamic,
+ ObjectType_Light,
+ //Etc
+
+ ObjectType_NUM_OF_TYPES,
+
+ ObjectType_Unknown = -1
+ };
+
+ enum UsePhysics
+ {
+ UsePhysics_UseFullPhysics,
+ UsePhysics_IgnoreGravity,
+ UsePhysics_IgnorePhysics,
+ UsePhysics_IgnoreCollision,
+
+ UsePhysics_Count,
+ UsePhysics_Unknown = -1
+ };
+
+ enum CollisionGeometryType
+ {
+ CollisionGeometryType_Box,
+ CollisionGeometryType_Sphere,
+
+ CollisionGeometryType_Count,
+ CollisionGeometryType_Unknown = -1
+ };
+
+ enum LightType
+ {
+ LightType_PointLight,
+ LightType_DirectionalLight,
+ LightType_SpotLight,
+
+ LightType_Count,
+ LightType_Unknown = -1
+ };
+
+ //Should this be moved somewhere else?
+ enum GameMode
+ {
+ GameMode_FreeForAll,
+ GameMode_TeamDeathMatch,
+ //Etc
+
+ GameMode_Count,
+ GameMode_Unknown = -1
+ };
+
+ enum WorldSize
+ {
+ WorldSize_Tiny,
+ WorldSize_Small,
+ WorldSize_Medium,
+ WorldSize_Big,
+ WorldSize_Humongous,
+
+ WorldSize_Count,
+ WorldSize_Unknown = -1
+ };
+
+
+ /************************************
+ Structs
+ *************************************/
+
+ struct FormatVersion
+ {
+ unsigned int formatVersionMajor;
+ unsigned int formatVersionMinor;
+
+ bool operator ==(const FormatVersion& obj)
+ {
+ return (this->formatVersionMajor != obj.formatVersionMajor && this->formatVersionMinor != obj.formatVersionMinor);
+ }
+
+ bool operator !=(const FormatVersion& obj)
+ {
+ return !(*this == obj);
+ }
+ };
+
+ struct ObjectTypeHeader
+ {
+ ObjectType typeID;
+ };
+
+ struct PhysicsObject
+ {
+ UsePhysics usePhysics;
+ float mass;
+ float inertiaMagnitude[3];
+ float inertiaRotation[3];
+ float frictionCoeffStatic;
+ float frictionCoeffDynamic;
+ CollisionGeometryType geometryType;
+ };
+
+ struct LevelMetaData : public ObjectTypeHeader
+ {
+ std::string levelName;
+ unsigned int levelVersion;
+ std::string levelDescription;
+ std::string levelAuthor;
+ unsigned int maxNumberOfPlayer;
+ WorldSize worldSize;
+ std::string overviewPicturePath;
+ std::vector gameModesSupported;
+ };
+
+ struct ObjectHeader : public ObjectTypeHeader, public PhysicsObject
+ {
+ //Model,
+ std::string ModelFile;
+ //Position
+ float position[3];
+ //Rotation
+ float rotation[3];
+ float angle;
+ //Scale
+ float scale[3];
+ };
+
+
+ /************************************
+ Lights
+ *************************************/
+
+ struct BasicLight : public ObjectTypeHeader
+ {
+ LightType lightType;
+ float ambientColor[3];
+ float diffuseColor[3];
+ float specularColor[3];
+ };
+
+ struct PointLight : public BasicLight
+ {
+ float position[3];
+ };
+
+ struct DirectionalLight : public BasicLight
+ {
+ float direction[3];
+ };
+
+ struct SpotLight : public BasicLight
+ {
+ float direction[3];
+ float range;
+ float attenuation[3];
+ };
+}
+
+#endif
\ No newline at end of file
diff --git a/Code/Game/DanBiasGame/GameClientState/LevelLoader/ParseFunctions.cpp b/Code/Game/DanBiasGame/GameClientState/LevelLoader/ParseFunctions.cpp
new file mode 100644
index 00000000..08823d3d
--- /dev/null
+++ b/Code/Game/DanBiasGame/GameClientState/LevelLoader/ParseFunctions.cpp
@@ -0,0 +1,111 @@
+//////////////////////////////////
+// Created by Sam Svensson 2013 //
+//////////////////////////////////
+
+#include "ParseFunctions.h"
+#include "../../../../Misc/Packing/Packing.h"
+#include
+
+using namespace Oyster::Packing;
+using namespace GameLogic::LevelFileLoader;
+using namespace GameLogic;
+using namespace std;
+
+namespace GameLogic
+{
+ namespace LevelFileLoader
+ {
+ void ParseObject(char* buffer, void *header, int size)
+ {
+ memcpy(header, buffer, size);
+ }
+
+ void ParseObject(char* buffer, ObjectHeader& header, int& size)
+ {
+ char tempName[128];
+ unsigned int tempSize = 0;
+ int start = 0;
+
+ memcpy(&header.typeID, &buffer[start], 4);
+ start += 4;
+
+ memcpy(&tempSize, &buffer[start], 4);
+ start += 4;
+
+ memcpy(&tempName, &buffer[start], tempSize);
+ header.ModelFile.assign(&tempName[0], &tempName[tempSize]);
+ start += tempSize;
+
+ //3 float[3], 1 float
+ memcpy(&header.position, &buffer[start], 40);
+ start += 40;
+
+ //2 float[3], 3 float, 2 uint
+ memcpy(&header.usePhysics, &buffer[start], 44);
+ start += 44;
+
+ size += start;
+ }
+
+ void ParseLevelMetaData(char* buffer, LevelMetaData &header, int &size)
+ {
+ int start = 0;
+ unsigned int tempSize;
+ char tempName[128];
+
+ memcpy(&header.typeID, &buffer[start], 4);
+ start += 4;
+
+ memcpy(&tempSize , &buffer[start], 4);
+ start += 4;
+
+ memcpy(&tempName, &buffer[start], tempSize);
+ header.levelName.assign(&tempName[0], &tempName[tempSize]);
+ start += tempSize;
+
+ memcpy(&header.levelVersion, &buffer[start], 4);
+ start += 4;
+
+ memcpy(&tempSize, &buffer[start], 4);
+ start +=4;
+
+ memcpy(&tempName, &buffer[start], tempSize);
+ header.levelDescription.assign(&tempName[0], &tempName[tempSize]);
+ start += tempSize;
+
+ memcpy(&tempSize, &buffer[start], 4);
+ start += 4;
+
+ memcpy(&tempName, &buffer[start], tempSize);
+ header.levelAuthor.assign(&tempName[0], &tempName[tempSize]);
+ start += tempSize;
+
+ memcpy(&header.maxNumberOfPlayer, &buffer[start], 4);
+ start += 4;
+
+ memcpy(&header.worldSize, &buffer[start], 4);
+ start += 4;
+
+ memcpy(&tempSize, &buffer[start], 4);
+ start += 4;
+
+ memcpy(&tempName, &buffer[start], tempSize);
+ header.overviewPicturePath.assign(&tempName[0], &tempName[tempSize]);
+ start += tempSize;
+
+ memcpy(&tempSize, &buffer[start], 4);
+ start += 4;
+
+ int temp;
+
+ for(int i = 0; i < tempSize; i++)
+ {
+ memcpy(&temp, &buffer[start], 4);
+ start += 4;
+ header.gameModesSupported.push_back((GameMode)temp);
+ }
+
+ size += start;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Code/Game/DanBiasGame/GameClientState/LevelLoader/ParseFunctions.h b/Code/Game/DanBiasGame/GameClientState/LevelLoader/ParseFunctions.h
new file mode 100644
index 00000000..f68a9289
--- /dev/null
+++ b/Code/Game/DanBiasGame/GameClientState/LevelLoader/ParseFunctions.h
@@ -0,0 +1,28 @@
+//////////////////////////////////
+// Created by Sam Svensson 2013 //
+//////////////////////////////////
+
+#ifndef PARSERFUNCTIONS_H
+#define PARSERFUNCTIONS_H
+#include "ObjectDefines.h"
+
+namespace GameLogic
+{
+ namespace LevelFileLoader
+ {
+ /*
+ These functions will copy data from where the buffer pointer points.
+ header is the destination where the data will be copied.
+ size is either the size of the data to be copied (if it is NOT sent by reference).
+ Or the current index that is being used to parse the entire file (if it is sent by reference) this means you have to increase size with the appropiate size after you have copied.
+
+ */
+
+ void ParseObject(char* buffer, void *header, int size);
+ void ParseObject(char* buffer, ObjectHeader& header, int& size);
+ void ParseLevelMetaData(char* buffer, LevelMetaData &header, int &size);
+ }
+}
+
+
+#endif
\ No newline at end of file
diff --git a/Code/Game/DanBiasGame/GameClientState/LobbyState.cpp b/Code/Game/DanBiasGame/GameClientState/LobbyState.cpp
index 98d192dd..9829b9a1 100644
--- a/Code/Game/DanBiasGame/GameClientState/LobbyState.cpp
+++ b/Code/Game/DanBiasGame/GameClientState/LobbyState.cpp
@@ -54,17 +54,18 @@ bool LobbyState::LoadModels(std::wstring file)
ModelInitData modelData;
- modelData.world = Oyster::Math3D::Float4x4::identity;
+ modelData.position = Oyster::Math::Float3(0,0,0);
+ modelData.rotation = Oyster::Math::Quaternion::identity;
+ modelData.scale = Oyster::Math::Float3(1,1,1);
modelData.visible = true;
- modelData.modelPath = L"box_2.dan";
+ modelData.modelPath = L"crate_colonists.dan";
// load models
privData->object[0] = new C_StaticObj();
privData->object[0]->Init(modelData);
- Oyster::Math3D::Float4x4 translate = Oyster::Math3D::TranslationMatrix(Oyster::Math::Float3(2,2,2));
- modelData.world = modelData.world * translate;
+ modelData.position = Oyster::Math::Float3(2,2,2);
- privData->object[1] = new C_DynamicObj();
+ privData->object[1] = new C_StaticObj();
privData->object[1]->Init(modelData);
return true;
}
diff --git a/Code/Game/DanBiasGame/GameClientState/LoginState.cpp b/Code/Game/DanBiasGame/GameClientState/LoginState.cpp
index 4b6c8df9..2a354d1b 100644
--- a/Code/Game/DanBiasGame/GameClientState/LoginState.cpp
+++ b/Code/Game/DanBiasGame/GameClientState/LoginState.cpp
@@ -53,26 +53,18 @@ bool LoginState::LoadModels(std::wstring file)
ModelInitData modelData;
- modelData.world = Oyster::Math3D::Float4x4::identity;
+ modelData.rotation = Oyster::Math::Quaternion::identity;
+ modelData.scale = Oyster::Math::Float3(1,1,1);
modelData.visible = true;
- modelData.modelPath = L"identityPlane.dan";
- // load models
- Oyster::Math3D::Float4x4 translate = Oyster::Math3D::TranslationMatrix(Oyster::Math::Float3(2,2,-2));
- Oyster::Math3D::Float4x4 rot = Oyster::Math3D::RotationMatrix(Oyster::Math::Float3(0 ,Utility::Value::Radian(90.0f), 0));
- Oyster::Math3D::Float4x4 scale = Oyster::Math3D::Float4x4::identity;
- int scaling = 2;
- scale.v[0].x = scaling;
- scale.v[1].y = scaling;
- scale.v[2].z = scaling;
+ modelData.modelPath = L"box.dan";
+
- modelData.world = translate; //scale * translate * rot;
- privData->object[0] = new C_DynamicObj();
+ modelData.position = Oyster::Math::Float3(2,2,2);
+ privData->object[0] = new C_StaticObj();
privData->object[0]->Init(modelData);
- translate = Oyster::Math3D::TranslationMatrix(Oyster::Math::Float3(0,0,-2));
- modelData.world = translate ;//* rot;
-
- privData->object[1] = new C_DynamicObj();
+ modelData.position = Oyster::Math::Float3(-2,0,-2);
+ privData->object[1] = new C_StaticObj();
privData->object[1]->Init(modelData);
return true;
}
diff --git a/Code/Game/GameLogic/AttatchmentMassDriver.cpp b/Code/Game/GameLogic/AttatchmentMassDriver.cpp
index 59be4542..a2002566 100644
--- a/Code/Game/GameLogic/AttatchmentMassDriver.cpp
+++ b/Code/Game/GameLogic/AttatchmentMassDriver.cpp
@@ -64,11 +64,11 @@ void AttatchmentMassDriver::Update(float dt)
state = heldObject->GetState();
Oyster::Math::Float3 ownerPos = owner->GetPosition();
Oyster::Physics::ICustomBody::State ownerState = owner->GetRigidBody()->GetState();
- Oyster::Math::Float3 up = -ownerState.GetGravityNormal();
+ Oyster::Math::Float3 up = -ownerState.GetOrientation().v[2];
up *= -0.3;
Oyster::Math::Float3 pos = ownerPos + up + (owner->GetLookDir().GetNormalized()*5);
- state.SetCenterPosition(pos);
+ state.centerPos = pos;
heldObject->SetState(state);
}
@@ -88,7 +88,7 @@ void AttatchmentMassDriver::ForcePush(const GameLogic::WEAPON_FIRE &usage, float
Oyster::Physics::API::Instance().ReleaseFromLimbo(heldObject);
pushForce = Oyster::Math::Float4(this->owner->GetLookDir()) * (700);
Oyster::Physics::ICustomBody::State state = heldObject->GetState();
- state.ApplyLinearImpulse((Oyster::Math::Float3)pushForce);
+ //state.ApplyLinearImpulse((Oyster::Math::Float3)pushForce);
heldObject->SetState(state);
hasObject = false;
@@ -118,7 +118,7 @@ void AttatchmentMassDriver::ForceZip(const WEAPON_FIRE &usage, float dt)
Oyster::Physics::Struct::CustomBodyState state = this->owner->GetRigidBody()->GetState();
//do something with state
- state.ApplyLinearImpulse(Oyster::Math::Float3(this->owner->GetLookDir()) * (500 * dt));
+ //state.ApplyLinearImpulse(Oyster::Math::Float3(this->owner->GetLookDir()) * (500 * dt));
this->owner->GetRigidBody()->SetState(state);
}
@@ -135,7 +135,7 @@ void AttatchmentMassDriver::ForcePull(const WEAPON_FIRE &usage, float dt)
//if no object has been picked up then suck objects towards you
Oyster::Math::Float4 pushForce = Oyster::Math::Float4(this->owner->GetLookDir()) * (100 * dt);
- Oyster::Math::Float4x4 aim = Oyster::Math3D::ViewMatrix_LookAtDirection(owner->GetLookDir(), owner->GetRigidBody()->GetGravityNormal(), owner->GetPosition());
+ Oyster::Math::Float4x4 aim = Oyster::Math3D::ViewMatrix_LookAtDirection(owner->GetLookDir(), owner->GetRigidBody()->GetState().GetOrientation().v[2].xyz, owner->GetPosition());
Oyster::Math::Float4x4 hitSpace = Oyster::Math3D::ProjectionMatrix_Perspective(Oyster::Math::pi/4,1,1,20);
Oyster::Collision3D::Frustrum hitFrustum = Oyster::Collision3D::Frustrum(Oyster::Math3D::ViewProjectionMatrix(aim,hitSpace));
diff --git a/Code/Game/GameLogic/CollisionManager.cpp b/Code/Game/GameLogic/CollisionManager.cpp
index e4e8923d..9c6f6aca 100644
--- a/Code/Game/GameLogic/CollisionManager.cpp
+++ b/Code/Game/GameLogic/CollisionManager.cpp
@@ -68,7 +68,7 @@ using namespace GameLogic;
Oyster::Physics::ICustomBody::State state;
state = obj.GetState();
- state.ApplyLinearImpulse(force);
+ //state.ApplyLinearImpulse(force);
obj.SetState(state);
}
@@ -130,7 +130,7 @@ using namespace GameLogic;
return;
state = obj->GetState();
- state.ApplyLinearImpulse(((forcePushData*)(args))->pushForce);
+ //state.ApplyLinearImpulse(((forcePushData*)(args))->pushForce);
obj->SetState(state);
}
diff --git a/Code/Game/GameLogic/Game.cpp b/Code/Game/GameLogic/Game.cpp
index 939056a1..c78abb09 100644
--- a/Code/Game/GameLogic/Game.cpp
+++ b/Code/Game/GameLogic/Game.cpp
@@ -82,6 +82,7 @@ Game::LevelData* Game::CreateLevel()
this->level = new LevelData();
this->level->level->InitiateLevel(1000);
+ //this->level->level->InitiateLevel("3bana.bias");
return this->level;
}
@@ -98,14 +99,18 @@ bool Game::NewFrame()
if(this->players[i]->player) this->players[i]->player->BeginFrame();
}
- API::Instance().Update();
+ API::Instance().UpdateWorld();
for (unsigned int i = 0; i < this->players.Size(); i++)
{
if(this->players[i]->player) this->players[i]->player->EndFrame();
+ gameInstance.onMoveFnc(this->players[i]);
}
-
- //gameInstance.onMoveFnc(this->level);
+ for (unsigned int i = 0; i < this->level->level->dynamicObjects.Size(); i++)
+ {
+ gameInstance.onMoveFnc(this->level->level->dynamicObjects[i]);
+ }
+
return true;
}
@@ -132,9 +137,9 @@ void Game::SetSubscription(GameEvent::ObjectDisabledFunction functionPointer)
bool Game::Initiate()
{
- API::Instance().Init((int)pow(2u, 9u), 1u, Oyster::Math::Float3());
- API::Instance().SetSubscription(Game::PhysicsOnDestroy);
- API::Instance().SetFrameTimeLength(this->frameTime);
+ API::Instance().Init();
+ //API::Instance().SetSubscription(Game::PhysicsOnDestroy);
+ //API::Instance().SetFrameTimeLength(this->frameTime);
this->initiated = true;
return true;
}
diff --git a/Code/Game/GameLogic/Game.h b/Code/Game/GameLogic/Game.h
index 2ae96ce3..601b0f0c 100644
--- a/Code/Game/GameLogic/Game.h
+++ b/Code/Game/GameLogic/Game.h
@@ -36,6 +36,8 @@ namespace GameLogic
int GetTeamID() const override;
PLAYER_STATE GetState() const override;
Oyster::Math::Float3 GetPosition() override;
+ Oyster::Math::Quaternion GetRotation() override;
+ Oyster::Math::Float3 GetScale() override;
Oyster::Math::Float4x4 GetOrientation() override;
int GetID() const override;
OBJECT_TYPE GetObjectType() const override;
@@ -50,6 +52,8 @@ namespace GameLogic
LevelData();
~LevelData();
Oyster::Math::Float3 GetPosition() override;
+ Oyster::Math::Quaternion GetRotation() override;
+ Oyster::Math::Float3 GetScale() override;
Oyster::Math::Float4x4 GetOrientation() override;
int GetID() const override;
OBJECT_TYPE GetObjectType() const override;
diff --git a/Code/Game/GameLogic/GameAPI.h b/Code/Game/GameLogic/GameAPI.h
index 3505b123..d51cf4a6 100644
--- a/Code/Game/GameLogic/GameAPI.h
+++ b/Code/Game/GameLogic/GameAPI.h
@@ -36,10 +36,22 @@ namespace GameLogic
public:
/********************************************************
* Gets players position
- * @param playerID: ID of the player whos position you want
+ * @return Returns the players position
********************************************************/
virtual Oyster::Math::Float3 GetPosition() = 0;
+ /********************************************************
+ * Gets players rotation as quaternion
+ * @return Returns a quaternion
+ ********************************************************/
+ virtual Oyster::Math::Quaternion GetRotation() = 0;
+
+ /********************************************************
+ * Gets players position
+ * @return Returns the player scale
+ ********************************************************/
+ virtual Oyster::Math::Float3 GetScale() = 0;
+
/********************************************************
* Gets players current orientation
* @param playerID: ID of the player whos position you want
diff --git a/Code/Game/GameLogic/GameLogic.vcxproj b/Code/Game/GameLogic/GameLogic.vcxproj
index 674773bf..7ae78fac 100644
--- a/Code/Game/GameLogic/GameLogic.vcxproj
+++ b/Code/Game/GameLogic/GameLogic.vcxproj
@@ -181,7 +181,7 @@
-
+
@@ -203,7 +203,7 @@
-
+
diff --git a/Code/Game/GameLogic/GameMode.cpp b/Code/Game/GameLogic/GameMode.cpp
deleted file mode 100644
index ba240fca..00000000
--- a/Code/Game/GameLogic/GameMode.cpp
+++ /dev/null
@@ -1,15 +0,0 @@
-#include "GameMode.h"
-
-using namespace GameLogic;
-
-
-GameMode::GameMode()
-{
-
-}
-
-
-GameMode::~GameMode(void)
-{
-
-}
diff --git a/Code/Game/GameLogic/GameModeType.cpp b/Code/Game/GameLogic/GameModeType.cpp
new file mode 100644
index 00000000..b48fd475
--- /dev/null
+++ b/Code/Game/GameLogic/GameModeType.cpp
@@ -0,0 +1,15 @@
+#include "GameModeType.h"
+
+using namespace GameLogic;
+
+
+GameModeType::GameModeType()
+{
+
+}
+
+
+GameModeType::~GameModeType(void)
+{
+
+}
diff --git a/Code/Game/GameLogic/GameMode.h b/Code/Game/GameLogic/GameModeType.h
similarity index 63%
rename from Code/Game/GameLogic/GameMode.h
rename to Code/Game/GameLogic/GameModeType.h
index d910c78c..8cc9fa37 100644
--- a/Code/Game/GameLogic/GameMode.h
+++ b/Code/Game/GameLogic/GameModeType.h
@@ -3,16 +3,16 @@
//////////////////////////////////////////////////
-#ifndef GAMEMODE_H
-#define GAMEMODE_H
+#ifndef GAMEMODETYPE_H
+#define GAMEMODETYPE_H
namespace GameLogic
{
- class GameMode
+ class GameModeType
{
public:
- GameMode(void);
- ~GameMode(void);
+ GameModeType(void);
+ ~GameModeType(void);
private:
diff --git a/Code/Game/GameLogic/Game_LevelData.cpp b/Code/Game/GameLogic/Game_LevelData.cpp
index 9bd3275a..b8006af3 100644
--- a/Code/Game/GameLogic/Game_LevelData.cpp
+++ b/Code/Game/GameLogic/Game_LevelData.cpp
@@ -20,6 +20,14 @@ Oyster::Math::Float3 Game::LevelData::GetPosition()
//return this->level->GetCenter();
return Oyster::Math::Float3();
}
+Oyster::Math::Quaternion Game::LevelData::GetRotation()
+{
+ return Oyster::Math::Quaternion();
+}
+Oyster::Math::Float3 Game::LevelData::GetScale()
+{
+ return Oyster::Math::Float3();
+}
Oyster::Math::Float4x4 Game::LevelData::GetOrientation()
{
//return this->level->GetOrientation();
diff --git a/Code/Game/GameLogic/Game_PlayerData.cpp b/Code/Game/GameLogic/Game_PlayerData.cpp
index 61c36dd1..7f24fbd4 100644
--- a/Code/Game/GameLogic/Game_PlayerData.cpp
+++ b/Code/Game/GameLogic/Game_PlayerData.cpp
@@ -6,26 +6,26 @@ using namespace GameLogic;
Game::PlayerData::PlayerData()
{
//set some stats that are appropriate to a player
- Oyster::Physics::API::SimpleBodyDescription sbDesc;
- sbDesc.centerPosition = Oyster::Math::Float3(0,308,0);
- sbDesc.size = Oyster::Math::Float3(0.5f,2,1);
- sbDesc.mass = 70;
- sbDesc.restitutionCoeff = 0.5;
- sbDesc.frictionCoeff_Static = 0.4;
- sbDesc.frictionCoeff_Dynamic = 0.3;
- sbDesc.rotation = Oyster::Math::Float3(0, Oyster::Math::pi, 0);
+ Oyster::Math::Float3 centerPosition = Oyster::Math::Float3(0,628,-25);
+ Oyster::Math::Float3 size = Oyster::Math::Float3(0.25f,1.0f,0.5f);
+ Oyster::Math::Float mass = 60;
+ Oyster::Math::Float restitutionCoeff = 0.5;
+ Oyster::Math::Float frictionCoeff_Static = 0.4;
+ Oyster::Math::Float frictionCoeff_Dynamic = 0.3;
+ //sbDesc.quaternion = Oyster::Math::Float3(0, Oyster::Math::pi, 0);
//create rigid body
- Oyster::Physics::ICustomBody *rigidBody = Oyster::Physics::API::Instance().CreateRigidBody(sbDesc).Release();
+ Oyster::Physics::ICustomBody* rigidBody = Oyster::Physics::API::Instance().AddCollisionBox(size, Oyster::Math::Float4(0, 0, 0, 1), centerPosition, mass, 0.5f, 0.8f, 0.6f );
//create player with this rigid body
- this->player = new Player(rigidBody,Player::PlayerCollisionBefore, Player::PlayerCollision, OBJECT_TYPE::OBJECT_TYPE_PLAYER);
+ this->player = new Player(rigidBody,Level::LevelCollisionBefore, Player::PlayerCollision, OBJECT_TYPE::OBJECT_TYPE_PLAYER);
this->player->GetRigidBody()->SetCustomTag(this);
- /*Oyster::Physics::ICustomBody::State state;
- this->player->GetRigidBody()->GetState(state);
- state.SetRotation(Oyster::Math::Float3(0, Oyster::Math::pi, 0));
- this->player->GetRigidBody()->SetState(state);
- player->EndFrame();*/
+
+ //Oyster::Physics::ICustomBody::State state;
+ //this->player->GetRigidBody()->GetState(state);
+ ////state.SetRotation(Oyster::Math::Float3(0, Oyster::Math::pi, 0));
+ //this->player->GetRigidBody()->SetState(state);
+ player->EndFrame();
}
Game::PlayerData::PlayerData(int playerID,int teamID)
{
@@ -48,6 +48,14 @@ Oyster::Math::Float3 Game::PlayerData::GetPosition()
{
return this->player->GetPosition();
}
+Oyster::Math::Quaternion Game::PlayerData::GetRotation()
+{
+ return this->player->GetRotation();
+}
+Oyster::Math::Float3 Game::PlayerData::GetScale()
+{
+ return this->player->GetScale();
+}
Oyster::Math::Float4x4 Game::PlayerData::GetOrientation()
{
return this->player->GetOrientation();
diff --git a/Code/Game/GameLogic/Level.cpp b/Code/Game/GameLogic/Level.cpp
index e449f14d..28f059e5 100644
--- a/Code/Game/GameLogic/Level.cpp
+++ b/Code/Game/GameLogic/Level.cpp
@@ -14,163 +14,163 @@ Level::Level(void)
Level::~Level(void)
{
delete this->levelObj;
- this->levelObj = 0;
+ this->levelObj = NULL;
}
+void Level::parseObjectType(ObjectTypeHeader* obj)
+{
+ /*switch (obj->objectTypeID)
+ {
+ case skySphere:
+ // save the skysphere to be able to rotate it
+ break;
+ case jumppad:
+ // save direction
+ break;
+ case portal:
+ // save portal destination
+ break;
+ case world:
+ // add gravitation well here
+ // add outer limit of the world
+ case spawn:
+ // save spawnpoint pos
+ break;
+ default:
+ break;
+ }*/
+}
+void Level::parsePhysicsObj(LevelLoaderInternal::BoundingVolumeBase* obj)
+{
+ // offset physObj med modelObj
+}
void Level::InitiateLevel(std::string levelPath)
{
+ LevelLoader ll;
+ std::vector> objects;
+ objects = ll.LoadLevel(levelPath);
+ int objCount = objects.size();
+ int modelCount = 0;
+ int staticObjCount = 0;
+ int dynamicObjCount = 0;
+ for (int i = 0; i < objCount; i++)
+ {
+ ObjectTypeHeader* obj = objects.at(i);
+ int id = obj->typeID;
+ switch (obj->typeID)
+ {
+ case ObjectType::ObjectType_LevelMetaData:
+ {
+ LevelMetaData* LevelObjData = ((LevelMetaData*)obj);
+ std::string levelName = LevelObjData->levelName;
+ // LevelObjData->worldSize;
+ }
+ break;
+ case ObjectType::ObjectType_Static:
+ {
+
+ ObjectHeader* staticObjData = ((ObjectHeader*)obj);
+ //LevelLoaderInternal::BoundingVolumeBase* staticObjPhysicData = ((ObjectHeader*)obj);
+ staticObjData->ModelFile;
+ ICustomBody* rigidBody_Static;
+
+ // collision shape
+ // radius, rotation in world, position in world, mass, restitution, static and dynamic friction
+ ICustomBody* rigidBody = API::Instance().AddCollisionSphere(599.2f, Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(0, 0, 0), 0, 0.5f, 0.8f, 0.6f);
+
+ // add rigidbody to the logical obj
+ // Object::DefaultCollisionBefore, Object::DefaultCollisionAfter for now, gamelogic will take care of this
+ // set object_type to objID
+ this->staticObjects.Push(new StaticObject(rigidBody,Object::DefaultCollisionBefore, Object::DefaultCollisionAfter, OBJECT_TYPE::OBJECT_TYPE_BOX));
+
+ this->staticObjects[staticObjCount]->objectID = modelCount++;
+ rigidBody->SetCustomTag(this->staticObjects[staticObjCount]);
+ }
+ break;
+ case ObjectType::ObjectType_Dynamic:
+ {
+ ObjectHeader* staticObjData = ((ObjectHeader*)obj);
+ staticObjData->ModelFile;
+
+ ICustomBody* rigidBody_Dynamic;
+
+ rigidBody_Dynamic = API::Instance().AddCollisionBox(Oyster::Math::Float3(0.5f, 0.5f, 0.5f), Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(0, 605 + i*5, 10), 5, 0.5f, 0.8f, 0.6f);
+
+ this->dynamicObjects.Push(new DynamicObject(rigidBody_Dynamic,Object::DefaultCollisionBefore, Object::DefaultCollisionAfter, OBJECT_TYPE::OBJECT_TYPE_BOX));
+ this->dynamicObjects[dynamicObjCount]->objectID = modelCount++;
+ rigidBody_Dynamic->SetCustomTag(this->dynamicObjects[dynamicObjCount]);
+ }
+ break;
+ case ObjectType::ObjectType_Light:
+ // read on client
+ break;
+ default:
+ break;
+ }
+ }
}
void Level::InitiateLevel(float radius)
{
- //float heading = Utility::Value::Radian(180.0f);
- //float attitude = Utility::Value::Radian(0.0f);
- //float bank = Utility::Value::Radian(0);
- //
- //double c1 = cos(heading/2);
- //double s1 = sin(heading/2);
- //double c2 = cos(attitude/2);
- //double s2 = sin(attitude/2);
- //double c3 = cos(bank/2);
- //double s3 = sin(bank/2);
- //double c1c2 = c1*c2;
- //double s1s2 = s1*s2;
- //double w =c1c2*c3 - s1s2*s3;
- //double x =c1c2*s3 + s1s2*c3;
- //double y =s1*c2*c3 + c1*s2*s3;
- //double z =c1*s2*c3 - s1*c2*s3;
- //double angle = 2 * acos(w);
- //
- //double norm = x*x+y*y+z*z;
- //if (norm < 0.001) { // when all euler angles are zero angle =0 so
- // // we can set axis to anything to avoid divide by zero
- // x=1;
- // y=z=0;
- //} else {
- // norm = sqrt(norm);
- // x /= norm;
- // y /= norm;
- // z /= norm;
- //}
-
int idCount = 100;
-
-// add level sphere
- API::SphericalBodyDescription sbDesc;
- sbDesc.centerPosition = Oyster::Math::Float4(0,0,0,1);
- sbDesc.ignoreGravity = true;
- sbDesc.radius = 300;
- sbDesc.mass = 10e12f;
- sbDesc.frictionCoeff_Static = 0;
- sbDesc.frictionCoeff_Dynamic = 0;
- //sbDesc.rotation =
- ICustomBody* rigidBody = API::Instance().CreateRigidBody(sbDesc).Release();
-
- ICustomBody::State state;
- rigidBody->GetState(state);
- state.SetRestitutionCoeff(0.2);
- rigidBody->SetState(state);
-
+ // add level sphere
+ ICustomBody* rigidBody = API::Instance().AddCollisionSphere(599.2f, Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(0, 0, 0), 0, 0.5f, 0.8f, 0.6f);
levelObj = new StaticObject(rigidBody, LevelCollisionBefore, LevelCollisionAfter, OBJECT_TYPE::OBJECT_TYPE_WORLD);
- levelObj->objectID = idCount++;
+ this->levelObj->objectID = idCount++;
rigidBody->SetCustomTag(levelObj);
-
-/*
-// add box
- API::SimpleBodyDescription sbDesc_TestBox;
- sbDesc_TestBox.centerPosition = Oyster::Math::Float4(10,320,0,0);
- sbDesc_TestBox.ignoreGravity = false;
- sbDesc_TestBox.mass = 50;
- sbDesc_TestBox.size = Oyster::Math::Float4(2,2,2,0);
-
-
+ /*
ICustomBody* rigidBody_TestBox;
int nrOfBoxex = 5;
int offset = 0;
for(int i =0; i< nrOfBoxex; i ++)
{
- sbDesc_TestBox.centerPosition = Oyster::Math::Float4(-20 +( i*7) ,320,20,0);
- rigidBody_TestBox = API::Instance().CreateRigidBody(sbDesc_TestBox).Release();
- rigidBody_TestBox->SetSubscription(Level::PhysicsOnMoveLevel);
+ rigidBody_TestBox = API::Instance().AddCollisionBox(Oyster::Math::Float3(0.5f, 0.5f, 0.5f), Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(0, 605 + i*5, 10), 5, 0.5f, 0.8f, 0.6f);
- DynamicObject *box = new DynamicObject(rigidBody_TestBox,Object::DefaultCollisionBefore, Object::DefaultCollisionAfter, OBJECT_TYPE::OBJECT_TYPE_BOX);
- box->objectID = idCount++;
- this->dynamicObjects.Push(box);
+ this->dynamicObjects.Push(new DynamicObject(rigidBody_TestBox,Object::DefaultCollisionBefore, Object::DefaultCollisionAfter, OBJECT_TYPE::OBJECT_TYPE_BOX));
+ this->dynamicObjects[i]->objectID = idCount++;
rigidBody_TestBox->SetCustomTag(this->dynamicObjects[i]);
}
+
offset += nrOfBoxex;
for(int i =0; i< nrOfBoxex; i ++)
{
- sbDesc_TestBox.centerPosition = Oyster::Math::Float4(-20,320, -20 +( i*7),0);
- rigidBody_TestBox = API::Instance().CreateRigidBody(sbDesc_TestBox).Release();
- rigidBody_TestBox->SetSubscription(Level::PhysicsOnMoveLevel);
+ rigidBody_TestBox = API::Instance().AddCollisionBox(Oyster::Math::Float3(0.5f, 0.5f, 0.5f), Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(0,5, -605 -( i*5)), 5);
this->dynamicObjects.Push(new DynamicObject(rigidBody_TestBox,Object::DefaultCollisionBefore, Object::DefaultCollisionAfter, OBJECT_TYPE::OBJECT_TYPE_BOX));
rigidBody_TestBox->SetCustomTag(this->dynamicObjects[i+offset]);
+
}
offset += nrOfBoxex;
for(int i =0; i< nrOfBoxex; i ++)
{
- sbDesc_TestBox.centerPosition = Oyster::Math::Float4(20,320,-20 + ( i*7),0);
- rigidBody_TestBox = API::Instance().CreateRigidBody(sbDesc_TestBox).Release();
- rigidBody_TestBox->SetSubscription(Level::PhysicsOnMoveLevel);
+ rigidBody_TestBox = API::Instance().AddCollisionBox(Oyster::Math::Float3(0.5f, 0.5f, 0.5f), Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(200, 620 + ( i*7), 0), 5);
this->dynamicObjects.Push(new DynamicObject(rigidBody_TestBox,Object::DefaultCollisionBefore, Object::DefaultCollisionAfter, OBJECT_TYPE::OBJECT_TYPE_BOX));
- rigidBody_TestBox->SetCustomTag(this->dynamicObjects[i+offset]);
+ rigidBody_TestBox->SetCustomTag(this->dynamicObjects[i+offset]);
}
offset += nrOfBoxex;
for(int i =0; i< nrOfBoxex; i ++)
{
- sbDesc_TestBox.centerPosition = Oyster::Math::Float4(-20 +( i*7) ,320,-20,0);
- rigidBody_TestBox = API::Instance().CreateRigidBody(sbDesc_TestBox).Release();
- rigidBody_TestBox->SetSubscription(Level::PhysicsOnMoveLevel);
+ rigidBody_TestBox = API::Instance().AddCollisionBox(Oyster::Math::Float3(0.5f, 0.5f, 0.5f), Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(5, 605 + i*5, 0), 5);
this->dynamicObjects.Push(new DynamicObject(rigidBody_TestBox,Object::DefaultCollisionBefore, Object::DefaultCollisionAfter, OBJECT_TYPE::OBJECT_TYPE_BOX));
- rigidBody_TestBox->SetCustomTag(this->dynamicObjects[i+offset]);
+ rigidBody_TestBox->SetCustomTag(this->dynamicObjects[i]);
+
}
+
+ // add crystal
-// add crystal
- API::SimpleBodyDescription sbDesc_Crystal;
- sbDesc_Crystal.centerPosition = Oyster::Math::Float4(10, 305, 0, 0);
- sbDesc_Crystal.ignoreGravity = false;
- sbDesc_Crystal.mass = 70;
- sbDesc_Crystal.size = Oyster::Math::Float4(2,3,2,0);
+ ICustomBody* rigidBody_Crystal = API::Instance().AddCollisionBox(Oyster::Math::Float3(0.5f, 0.5f, 0.5f), Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(10, 605, 0), 5);
- ICustomBody* rigidBody_Crystal = API::Instance().CreateRigidBody(sbDesc_Crystal).Release();
- rigidBody_Crystal->SetSubscription(Level::PhysicsOnMoveLevel);
- DynamicObject *cry = new DynamicObject(rigidBody_Crystal,Object::DefaultCollisionBefore, Object::DefaultCollisionAfter, OBJECT_TYPE::OBJECT_TYPE_BOX);
- cry->objectID = idCount++;
- this->dynamicObjects.Push(cry);
+ this->dynamicObjects.Push(new DynamicObject(rigidBody_Crystal,Object::DefaultCollisionBefore, Object::DefaultCollisionAfter, OBJECT_TYPE::OBJECT_TYPE_BOX));
rigidBody_Crystal->SetCustomTag(this->dynamicObjects[nrOfBoxex]);
-
-
-// add house
- API::SimpleBodyDescription sbDesc_House;
- //sbDesc_House.centerPosition = Oyster::Math::Float4(212, 212, 0, 0);
- sbDesc_House.centerPosition = Oyster::Math::Float4(-50, 290, 0, 0);
- sbDesc_House.ignoreGravity = false;
- sbDesc_House.rotation = Oyster::Math::Float3(0 ,Utility::Value::Radian(90.0f), 0);
- sbDesc_House.mass = 70;
- sbDesc_House.size = Oyster::Math::Float4(40,40,40,0);
-
-
- ICustomBody* rigidBody_House = API::Instance().CreateRigidBody(sbDesc_House).Release();
- rigidBody_House->SetSubscription(Level::PhysicsOnMoveLevel);
+ // add house
+ ICustomBody* rigidBody_House =API::Instance().AddCollisionBox(Oyster::Math::Float3(0.5f, 0.5f, 0.5f), Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(10, 905, 0), 0);
this->staticObjects.Push(new StaticObject(rigidBody_House,Object::DefaultCollisionBefore, Object::DefaultCollisionAfter, OBJECT_TYPE::OBJECT_TYPE_GENERIC));
rigidBody_House->SetCustomTag(this->staticObjects[0]);
- rigidBody_House->GetState(state);
- Oyster::Math::Float4x4 world = state.GetOrientation();
-
-*/
-
- // add gravitation
- API::Gravity gravityWell;
- gravityWell.gravityType = API::Gravity::GravityType_Well;
- gravityWell.well.mass = 1e17f;
- gravityWell.well.position = Oyster::Math::Float4(0,0,0,1);
- API::Instance().AddGravity(gravityWell);
+ */
}
void Level::AddPlayerToTeam(Player *player, int teamID)
diff --git a/Code/Game/GameLogic/Level.h b/Code/Game/GameLogic/Level.h
index cc34408b..581d1ee0 100644
--- a/Code/Game/GameLogic/Level.h
+++ b/Code/Game/GameLogic/Level.h
@@ -8,11 +8,12 @@
#include "Player.h"
#include "StaticObject.h"
#include "DynamicObject.h"
-#include "GameMode.h"
+#include "GameModeType.h"
#include "Player.h"
#include "PhysicsAPI.h"
#include "TeamManager.h"
#include "DynamicArray.h"
+#include "LevelLoader/LevelLoader.h"
namespace GameLogic
{
@@ -29,8 +30,10 @@ namespace GameLogic
* @param levelPath: Path to a file that contains all information on the level
********************************************************/
void InitiateLevel(std::string levelPath);
- void Level::InitiateLevel(float radius);
+ void InitiateLevel(float radius);
+ void parseObjectType(ObjectTypeHeader* obj);
+ void parsePhysicsObj(LevelLoaderInternal::BoundingVolumeBase* obj);
/********************************************************
* Creates a team in the level
* @param teamSize: The size of the team you want to create
@@ -65,11 +68,11 @@ namespace GameLogic
static void PhysicsOnMoveLevel(const Oyster::Physics::ICustomBody *object);
- private:
+ //private:
TeamManager teamManager;
Utility::DynamicMemory::DynamicArray> staticObjects;
Utility::DynamicMemory::DynamicArray> dynamicObjects;
- GameMode gameMode;
+ GameModeType gameMode;
Utility::DynamicMemory::SmartPointer rigidBodyLevel;
StaticObject *levelObj;
diff --git a/Code/Game/GameLogic/LevelLoader/LevelLoader.cpp b/Code/Game/GameLogic/LevelLoader/LevelLoader.cpp
index 55a39725..8fe880f3 100644
--- a/Code/Game/GameLogic/LevelLoader/LevelLoader.cpp
+++ b/Code/Game/GameLogic/LevelLoader/LevelLoader.cpp
@@ -17,7 +17,14 @@ struct LevelLoader::PrivData
LevelLoader::LevelLoader()
: pData(new PrivData)
{
- pData->folderPath = "Standard path";
+ //standard path
+ pData->folderPath = "";
+}
+
+LevelLoader::LevelLoader(std::string folderPath)
+ : pData(new PrivData)
+{
+ pData->folderPath = folderPath;
}
LevelLoader::~LevelLoader()
@@ -26,10 +33,20 @@ LevelLoader::~LevelLoader()
std::vector> LevelLoader::LoadLevel(std::string fileName)
{
- return pData->parser.Parse(fileName);
+ return pData->parser.Parse(pData->folderPath + fileName);
}
LevelMetaData LevelLoader::LoadLevelHeader(std::string fileName)
{
- return pData->parser.ParseHeader(fileName);
+ return pData->parser.ParseHeader(pData->folderPath + fileName);
+}
+
+std::string LevelLoader::GetFolderPath()
+{
+ return this->pData->folderPath;
+}
+
+void LevelLoader::SetFolderPath(std::string folderPath)
+{
+
}
\ No newline at end of file
diff --git a/Code/Game/GameLogic/LevelLoader/LevelLoader.h b/Code/Game/GameLogic/LevelLoader/LevelLoader.h
index bcd6e587..184a7005 100644
--- a/Code/Game/GameLogic/LevelLoader/LevelLoader.h
+++ b/Code/Game/GameLogic/LevelLoader/LevelLoader.h
@@ -17,11 +17,15 @@ namespace GameLogic
public:
LevelLoader();
+ /***********************************************************
+ * Lets you set the standard folderpath for the levels
+ ********************************************************/
+ LevelLoader(std::string folderPath);
~LevelLoader();
/********************************************************
* Loads the level and objects from file.
- * @param fileName: Path to the level-file that you want to load.
+ * @param fileName: Path/name to the level-file that you want to load.
* @return: Returns all structs with objects and information about the level.
********************************************************/
std::vector> LoadLevel(std::string fileName);
@@ -33,10 +37,20 @@ namespace GameLogic
********************************************************/
LevelMetaData LoadLevelHeader(std::string fileName); //.
+ /***********************************************************
+ * @return: Returns the current standard folder path
+ ********************************************************/
+ std::string GetFolderPath();
+
+ /***********************************************************
+ * Sets the standard folder path
+ ********************************************************/
+ void SetFolderPath(std::string folderPath);
+
private:
struct PrivData;
Utility::DynamicMemory::SmartPointer pData;
- };
+ };
}
#endif
\ No newline at end of file
diff --git a/Code/Game/GameLogic/LevelLoader/LevelParser.cpp b/Code/Game/GameLogic/LevelLoader/LevelParser.cpp
index 33567cc9..f66fbe08 100644
--- a/Code/Game/GameLogic/LevelLoader/LevelParser.cpp
+++ b/Code/Game/GameLogic/LevelLoader/LevelParser.cpp
@@ -13,7 +13,7 @@ using namespace Utility::DynamicMemory;
LevelParser::LevelParser()
{
- formatVersion.formatVersionMajor = 2;
+ formatVersion.formatVersionMajor = 3;
formatVersion.formatVersionMinor = 0;
}
@@ -71,7 +71,6 @@ std::vector> LevelParser::Parse(std::string filen
{
//These three does not have any specail variables at this time.
//There for they are using the same 'parser'.
- case ObjectSpecialType_World:
case ObjectSpecialType_Building:
case ObjectSpecialType_Damaging:
case ObjectSpecialType_Explosive:
@@ -113,14 +112,24 @@ std::vector> LevelParser::Parse(std::string filen
break;
}
- case ObjectSpecialType_SpawnPoint:
+
+ case ObjectSpecialType_World:
{
- SpawnPointAttributes* header = new SpawnPointAttributes;
+ WorldAttributes* header = new WorldAttributes;
ParseObject(&buffer[counter], *header, counter);
- ParseObject(&buffer[counter], header->spawnPosition, 12);
+ ParseObject(&buffer[counter], &header->worldSize, 8);
objects.push_back(header);
+ break;
+ }
+ case ObjectSpecialType_Sky:
+ {
+ SkyAttributes* header = new SkyAttributes;
+ ParseObject(&buffer[counter], *header, counter);
+
+ ParseObject(&buffer[counter], &header->skySize, 4);
+ objects.push_back(header);
break;
}
default:
@@ -239,9 +248,6 @@ LevelMetaData LevelParser::ParseHeader(std::string filename)
case ObjectSpecialType_Portal:
counter += sizeof(12);
break;
- case ObjectSpecialType_SpawnPoint:
- counter += sizeof(12);
- break;
default:
break;
}
diff --git a/Code/Game/GameLogic/LevelLoader/ObjectDefines.h b/Code/Game/GameLogic/LevelLoader/ObjectDefines.h
index d87e42b2..05d09714 100644
--- a/Code/Game/GameLogic/LevelLoader/ObjectDefines.h
+++ b/Code/Game/GameLogic/LevelLoader/ObjectDefines.h
@@ -32,7 +32,7 @@ namespace GameLogic
ObjectSpecialType_JumpPad,
ObjectSpecialType_BoostPad,
ObjectSpecialType_Portal,
- ObjectSpecialType_SpawnPoint,
+ ObjectSpecialType_Sky,
ObjectSpecialType_Count,
ObjectSpecialType_Unknown = -1
@@ -134,18 +134,22 @@ namespace GameLogic
namespace LevelLoaderInternal
{
- const FormatVersion boundingVolumeVersion(1, 0);
+ const FormatVersion boundingVolumeVersion(2, 0);
struct BoundingVolumeBase
{
+ CollisionGeometryType geoType;
float position[3];
+ float rotation[4];
+ float frictionCoeffStatic;
+ float frictionCoeffDynamic;
+ float restitutionCoeff;
+ float mass;
};
struct BoundingVolumeBox : public BoundingVolumeBase
{
float size[3];
- float angularAxis[3];
- float angle;
};
struct BoundingVolumeSphere : public BoundingVolumeBase
@@ -156,8 +160,6 @@ namespace GameLogic
struct BoundingVolumeCylinder : public BoundingVolumeBase
{
float length;
- float angularAxis[3];
- float angle;
float radius;
};
@@ -172,17 +174,6 @@ namespace GameLogic
};
};
- struct PhysicsObject
- {
- UsePhysics usePhysics;
- float mass;
- float inertiaMagnitude[3];
- float inertiaRotation[3];
- float frictionCoeffStatic;
- float frictionCoeffDynamic;
- float restitutionCoeff;
- BoundingVolume boundingVolume;
- };
}
struct LevelMetaData : public ObjectTypeHeader
@@ -200,7 +191,7 @@ namespace GameLogic
};
- struct ObjectHeader : public ObjectTypeHeader, public LevelLoaderInternal::PhysicsObject
+ struct ObjectHeader : public ObjectTypeHeader
{
//Special type id for special objects: portal, jumppad, exploding objects, etc.
ObjectSpecialType specialTypeID;
@@ -208,12 +199,13 @@ namespace GameLogic
std::string ModelFile;
//Position
float position[3];
- //Rotation
- float rotation[3];
- float angle;
+ //Rotation Quaternion
+ float rotation[4];
//Scale
float scale[3];
+ ::GameLogic::LevelLoaderInternal::BoundingVolume boundingVolume;
+
virtual ~ObjectHeader(){}
};
@@ -232,11 +224,19 @@ namespace GameLogic
float destination[3];
};
- struct SpawnPointAttributes : public ObjectHeader
+ struct WorldAttributes : public ObjectHeader
{
- float spawnPosition[3];
+ float worldSize;
+ float atmoSphereSize;
};
+ struct SkyAttributes : public ObjectHeader
+ {
+ float skySize;
+ };
+
+
+
/************************************
Lights
*************************************/
diff --git a/Code/Game/GameLogic/LevelLoader/ParseFunctions.cpp b/Code/Game/GameLogic/LevelLoader/ParseFunctions.cpp
index e8c055b3..d917a146 100644
--- a/Code/Game/GameLogic/LevelLoader/ParseFunctions.cpp
+++ b/Code/Game/GameLogic/LevelLoader/ParseFunctions.cpp
@@ -16,6 +16,7 @@ namespace GameLogic
{
namespace LevelFileLoader
{
+ //can parse any struct without strings or char[]
void ParseObject(char* buffer, void *header, int size)
{
memcpy(header, buffer, size);
@@ -44,11 +45,6 @@ namespace GameLogic
//3 float[3], 1 float
memcpy(&header.position, &buffer[start], 40);
start += 40;
-
- //Physics struct
- //2 float[3], 4 float, 1 uint
- memcpy(&header.usePhysics, &buffer[start], 44);
- start += 44;
//Read path for bounding volume
ParseBoundingVolume(&buffer[start], header.boundingVolume, start);
@@ -122,7 +118,7 @@ namespace GameLogic
int start = 0;
int tempSize = 0;
char tempName[128];
-
+
memcpy(&tempSize, &buffer[start], 4);
start += 4;
@@ -132,39 +128,41 @@ namespace GameLogic
fileName.assign(&tempName[0], &tempName[tempSize]);
start += tempSize;
+ size += start;
+
//Läs in filen.
int fileLength = 0;
Loader loader;
char* buf = loader.LoadFile("E:\\Dropbox\\Programming\\Github\\Danbias\\Bin\\Content\\Worlds\\cgf\\"+ fileName, fileLength);
-
- LevelLoaderInternal::FormatVersion version;
- memcpy(&version, &buffer[0], sizeof(version));
- memcpy(&volume.geoType, &buf[8], sizeof(volume.geoType));
- //start += sizeof(volume.geoType);
+ start = 0;
+ LevelLoaderInternal::FormatVersion version;
+ memcpy(&version, &buf[0], sizeof(version));
+ start += 4;
+
+ memcpy(&volume.geoType, &buf[start], sizeof(volume.geoType));
+ start += sizeof(volume.geoType);
switch(volume.geoType)
{
case CollisionGeometryType_Box:
- memcpy(&volume.box, &buf[12], sizeof(volume.box));
- //start += sizeof(volume.box);
+ memcpy(&volume.box, &buf[start], sizeof(volume.box));
+ start += sizeof(volume.box);
break;
case CollisionGeometryType_Sphere:
- memcpy(&volume.sphere, &buf[12], sizeof(volume.sphere));
- //start += sizeof(volume.sphere);
+ memcpy(&volume.sphere, &buf[start], sizeof(volume.sphere));
+ start += sizeof(volume.sphere);
break;
case CollisionGeometryType_Cylinder:
- memcpy(&volume.cylinder, &buf[12], sizeof(volume.cylinder));
- //start += sizeof(volume.cylinder);
+ memcpy(&volume.cylinder, &buf[start], sizeof(volume.cylinder));
+ start += sizeof(volume.cylinder);
break;
default:
break;
}
-
- size += start;
}
}
}
\ No newline at end of file
diff --git a/Code/Game/GameLogic/Object.cpp b/Code/Game/GameLogic/Object.cpp
index c2b99d6f..78141e5f 100644
--- a/Code/Game/GameLogic/Object.cpp
+++ b/Code/Game/GameLogic/Object.cpp
@@ -15,84 +15,54 @@ const Game *Object::gameInstance = (Game*)(&Game::Instance());
Object::Object()
{
- API::SimpleBodyDescription sbDesc;
- this->rigidBody = API::Instance().CreateRigidBody(sbDesc).Release();
- Oyster::Physics::API::Instance().AddObject(rigidBody);
+ this->rigidBody = API::Instance().AddCollisionBox(Oyster::Math::Float3(0.0f, 0.0f, 0.0f), Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(0, 0, 0), 0, 0.5f, 0.8f, 0.6f);
this->type = OBJECT_TYPE::OBJECT_TYPE_UNKNOWN;
this->objectID = GID();
- this->currPhysicsState = this->rigidBody->GetState();
- this->newPhysicsState = this->currPhysicsState;
}
Object::Object(OBJECT_TYPE type)
{
- API::SimpleBodyDescription sbDesc;
-
- this->rigidBody = API::Instance().CreateRigidBody(sbDesc).Release();
- Oyster::Physics::API::Instance().AddObject(rigidBody);
+ this->rigidBody = API::Instance().AddCollisionBox(Oyster::Math::Float3(0.0f, 0.0f, 0.0f), Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(0, 0, 0), 0, 0.5f, 0.8f, 0.6f);
this->type = type;
this->objectID = GID();
- this->currPhysicsState = this->rigidBody->GetState();
- this->newPhysicsState = this->currPhysicsState;
}
Object::Object(Oyster::Physics::ICustomBody *rigidBody, OBJECT_TYPE type)
{
- Oyster::Physics::API::Instance().AddObject(rigidBody);
this->rigidBody = rigidBody;
this->type = type;
this->objectID = GID();
- this->currPhysicsState = this->rigidBody->GetState();
- this->newPhysicsState = this->currPhysicsState;
}
Object::Object(void* collisionFuncBefore, void* collisionFuncAfter, OBJECT_TYPE type)
{
- API::SimpleBodyDescription sbDesc;
-
- this->rigidBody = API::Instance().CreateRigidBody(sbDesc).Release();
- Oyster::Physics::API::Instance().AddObject(rigidBody);
+ this->rigidBody = API::Instance().AddCollisionBox(Oyster::Math::Float3(0.0f, 0.0f, 0.0f), Oyster::Math::Float4(0, 0, 0, 1), Oyster::Math::Float3(0, 0, 0), 0, 0.5f, 0.8f, 0.6f);
this->type = type;
this->objectID = GID();
- this->currPhysicsState = this->rigidBody->GetState();
- this->newPhysicsState = this->currPhysicsState;
}
Object::Object(Oyster::Physics::ICustomBody *rigidBody ,void* collisionFuncBefore, void* collisionFuncAfter, OBJECT_TYPE type)
{
- Oyster::Physics::API::Instance().AddObject(rigidBody);
-
this->rigidBody = rigidBody;
- this->rigidBody->SetSubscription((Oyster::Physics::ICustomBody::EventAction_BeforeCollisionResponse)(collisionFuncBefore));
- this->rigidBody->SetSubscription((Oyster::Physics::ICustomBody::EventAction_AfterCollisionResponse)(collisionFuncAfter));
this->type = type;
this->objectID = GID();
- this->currPhysicsState = this->rigidBody->GetState();
- this->newPhysicsState = this->currPhysicsState;
}
Object::Object(Oyster::Physics::ICustomBody *rigidBody ,Oyster::Physics::ICustomBody::SubscriptMessage (*collisionFuncBefore)(Oyster::Physics::ICustomBody *proto,Oyster::Physics::ICustomBody *deuter), Oyster::Physics::ICustomBody::SubscriptMessage (*collisionFuncAfter)(Oyster::Physics::ICustomBody *proto,Oyster::Physics::ICustomBody *deuter,Oyster::Math::Float kineticEnergyLoss), OBJECT_TYPE type)
{
- Oyster::Physics::API::Instance().AddObject(rigidBody);
-
this->rigidBody = rigidBody;
- this->rigidBody->SetSubscription((Oyster::Physics::ICustomBody::EventAction_BeforeCollisionResponse)(collisionFuncBefore));
- this->rigidBody->SetSubscription((Oyster::Physics::ICustomBody::EventAction_AfterCollisionResponse)(collisionFuncAfter));
-
this->type = type;
this->objectID = GID();
- this->currPhysicsState = this->rigidBody->GetState();
- this->newPhysicsState = this->currPhysicsState;
}
void Object::ApplyLinearImpulse(Oyster::Math::Float3 force)
{
- newPhysicsState.ApplyLinearImpulse(force);
+
}
@@ -118,84 +88,17 @@ Oyster::Physics::ICustomBody* Object::GetRigidBody()
void Object::BeginFrame()
{
- if(currPhysicsState.GetLinearMomentum() !=currPhysicsState.GetLinearMomentum())
- {
- //error
- int i =0 ;
- }
- if(currPhysicsState.GetCenterPosition() !=currPhysicsState.GetCenterPosition())
- {
- //error
- int i =0 ;
- }
- if(currPhysicsState.GetAngularAxis() !=currPhysicsState.GetAngularAxis())
- {
- //error
- int i =0 ;
- }
- this->rigidBody->SetState(this->newPhysicsState);
+
}
// update physic
void Object::EndFrame()
{
- if(currPhysicsState.GetLinearMomentum() !=currPhysicsState.GetLinearMomentum())
- {
- //error
- int i =0 ;
- }
- this->currPhysicsState = this->rigidBody->GetState();
- if(currPhysicsState.GetLinearMomentum() !=currPhysicsState.GetLinearMomentum())
- {
- //error
- int i =0 ;
- }
- if(currPhysicsState.GetGravityNormal() !=currPhysicsState.GetGravityNormal())
- {
- //error
- int i =0 ;
- }
-
- if(currPhysicsState.GetGravityNormal()!= Float3::null)
- {
- Oyster::Math::Float4 axis;
- Oyster::Math3D::SnapAngularAxis(Oyster::Math::Float4(currPhysicsState.GetAngularAxis(), 0), Oyster::Math::Float4::standard_unit_y, -Oyster::Math::Float4(currPhysicsState.GetGravityNormal()), axis);
- if(axis !=axis)
- {
- //error
- int i =0 ;
- }
- currPhysicsState.SetRotation(axis.xyz);
- currPhysicsState.SetAngularMomentum(Float3::null);
- Oyster::Math::Float3 debug = ::LinearAlgebra3D::WorldAxisOf(::LinearAlgebra3D::Rotation(axis.xyz), Oyster::Math::Float3::standard_unit_y);
- debug += currPhysicsState.GetGravityNormal();
- }
- Oyster::Math::Float3 pos = currPhysicsState.GetCenterPosition();
- Oyster::Math::Float3 up = -currPhysicsState.GetGravityNormal();
- //300, 0,0,
- //1,0,0
-
- if( pos.GetLength() < 303.5f)
- {
- Oyster::Math::Float moveUp = 303.5 - pos.GetLength();
- up *= moveUp;
-
- currPhysicsState.SetCenterPosition(pos + up);
- }
-
-
- if(currPhysicsState.GetLinearMomentum() !=currPhysicsState.GetLinearMomentum())
- {
- //error
- int i =0 ;
- }
-
- this->newPhysicsState = this->currPhysicsState;
}
void Object::setBeforeCollisonFunc(Oyster::Physics::ICustomBody::SubscriptMessage (*collisionFuncBefore)(Oyster::Physics::ICustomBody *proto,Oyster::Physics::ICustomBody *deuter))
{
- this->rigidBody->SetSubscription((Oyster::Physics::ICustomBody::EventAction_BeforeCollisionResponse)(collisionFuncBefore));
+ //this->rigidBody->SetSubscription((Oyster::Physics::ICustomBody::EventAction_BeforeCollisionResponse)(collisionFuncBefore));
}
void Object::setAfterCollisonFunc(Oyster::Physics::ICustomBody::SubscriptMessage (*collisionFuncAfter)(Oyster::Physics::ICustomBody *proto,Oyster::Physics::ICustomBody *deuter,Oyster::Math::Float kineticEnergyLoss))
{
@@ -206,7 +109,19 @@ Oyster::Math::Float3 Object::GetPosition()
{
Oyster::Physics::ICustomBody::State state;
state = this->rigidBody->GetState();
- return state.GetCenterPosition();
+ return state.centerPos;
+}
+Oyster::Math::Quaternion Object::GetRotation()
+{
+ Oyster::Physics::ICustomBody::State state;
+ state = this->rigidBody->GetState();
+ return state.quaternion;
+}
+Oyster::Math::Float3 Object::GetScale()
+{
+ Oyster::Physics::ICustomBody::State state;
+ state = this->rigidBody->GetState();
+ return Float3();
}
Oyster::Math::Float4x4 Object::GetOrientation()
{
diff --git a/Code/Game/GameLogic/Object.h b/Code/Game/GameLogic/Object.h
index 48343c6a..293ba85d 100644
--- a/Code/Game/GameLogic/Object.h
+++ b/Code/Game/GameLogic/Object.h
@@ -25,12 +25,14 @@ namespace GameLogic
Object(Oyster::Physics::ICustomBody *rigidBody ,Oyster::Physics::ICustomBody::SubscriptMessage (*collisionFuncBefore)(Oyster::Physics::ICustomBody *proto,Oyster::Physics::ICustomBody *deuter), Oyster::Physics::ICustomBody::SubscriptMessage (*collisionFuncAfter)(Oyster::Physics::ICustomBody *proto,Oyster::Physics::ICustomBody *deuter,Oyster::Math::Float kineticEnergyLoss), OBJECT_TYPE type);
~Object(void);
- // API overrides
- OBJECT_TYPE GetObjectType() const;
- int GetID() const;
- Oyster::Math::Float3 GetPosition();
- Oyster::Math::Float4x4 GetOrientation();
+ OBJECT_TYPE GetObjectType() const override;
+ int GetID() const override;
+ Oyster::Math::Float3 GetPosition() override;
+ Oyster::Math::Quaternion GetRotation() override;
+ Oyster::Math::Float3 GetScale() override;
+ Oyster::Math::Float4x4 GetOrientation() override;
+ void setID(int id);
Oyster::Physics::ICustomBody* GetRigidBody();
void ApplyLinearImpulse(Oyster::Math::Float3 force);
@@ -44,14 +46,12 @@ namespace GameLogic
static Oyster::Physics::ICustomBody::SubscriptMessage DefaultCollisionBefore(Oyster::Physics::ICustomBody *rigidBodyLevel, Oyster::Physics::ICustomBody *obj);
static Oyster::Physics::ICustomBody::SubscriptMessage DefaultCollisionAfter(Oyster::Physics::ICustomBody *rigidBodyLevel, Oyster::Physics::ICustomBody *obj, Oyster::Math::Float kineticEnergyLoss);
- public: //TODO: Hax This should be private when level is dynamic
+ public: //HACK: This should be private when level is dynamic
OBJECT_TYPE type;
int objectID;
protected:
Oyster::Physics::ICustomBody *rigidBody;
- Oyster::Physics::ICustomBody::State newPhysicsState;
- Oyster::Physics::ICustomBody::State currPhysicsState;
static const Game* gameInstance;
Oyster::Math::Float3 currLook;
diff --git a/Code/Game/GameLogic/Player.cpp b/Code/Game/GameLogic/Player.cpp
index 6a2ff218..acbb33a9 100644
--- a/Code/Game/GameLogic/Player.cpp
+++ b/Code/Game/GameLogic/Player.cpp
@@ -70,12 +70,11 @@ void Player::EndFrame()
Object::EndFrame();
// rotate
- Oyster::Math::Float3 up = currPhysicsState.GetOrientation().v[1];
- Oyster::Math::Float3 deltaAxis = up * (-dx * 0.02) ;
+ //Oyster::Math::Float3 up = currPhysicsState.GetOrientation().v[1];
+ //Oyster::Math::Float3 deltaAxis = up * (-dx * 0.02) ;
- currPhysicsState.AddRotation(deltaAxis);
- dx = 0;
- this->newPhysicsState = this->currPhysicsState;
+ //currPhysicsState.AddRotation(deltaAxis);
+
}
void Player::Move(const PLAYER_MOVEMENT &movement)
@@ -106,32 +105,32 @@ void Player::Move(const PLAYER_MOVEMENT &movement)
void Player::MoveForward()
{
- Oyster::Math::Float3 forward = currPhysicsState.GetOrientation().v[2];
+ Oyster::Math::Float3 forward = this->rigidBody->GetState().GetOrientation().v[2];
//Oyster::Math::Float3 forward = lookDir;
- newPhysicsState.ApplyLinearImpulse(forward * (MOVE_FORCE * this->gameInstance->GetFrameTime()));
+ rigidBody->SetLinearVelocity( 10 * forward.GetNormalized() );
}
void Player::MoveBackwards()
{
- Oyster::Math::Float3 forward = currPhysicsState.GetOrientation().v[2];
+ Oyster::Math::Float3 forward = this->rigidBody->GetState().GetOrientation().v[2];
//Oyster::Math::Float3 forward = lookDir;
- newPhysicsState.ApplyLinearImpulse(-forward * MOVE_FORCE * this->gameInstance->GetFrameTime());
+ rigidBody->SetLinearVelocity( 10 * -forward.GetNormalized() );
}
void Player::MoveRight()
{
//Do cross product with forward vector and negative gravity vector
- Oyster::Math::Float3 forward = currPhysicsState.GetOrientation().v[2];
+ Oyster::Math::Float3 forward = this->rigidBody->GetState().GetOrientation().v[2];
+
//Oyster::Math::Float3 forward = lookDir;
- Oyster::Math::Float3 r = (-currPhysicsState.GetGravityNormal()).Cross(forward);
- newPhysicsState.ApplyLinearImpulse(-r * MOVE_FORCE * this->gameInstance->GetFrameTime());
-
+ Oyster::Math::Float3 r = (-this->rigidBody->GetState().centerPos.Normalize()).Cross(forward);
+ rigidBody->SetLinearVelocity(r * 10);
}
void Player::MoveLeft()
{
//Do cross product with forward vector and negative gravity vector
- Oyster::Math::Float3 forward = currPhysicsState.GetOrientation().v[2];
+ Oyster::Math::Float3 forward = this->rigidBody->GetState().GetOrientation().v[2];
//Oyster::Math::Float3 forward = lookDir;
- Oyster::Math::Float3 r = (-currPhysicsState.GetGravityNormal()).Cross(forward); //Still get zero
- newPhysicsState.ApplyLinearImpulse(r * MOVE_FORCE * this->gameInstance->GetFrameTime());
+ Oyster::Math::Float3 r = (-this->rigidBody->GetState().centerPos.Normalize()).Cross(forward);
+ rigidBody->SetLinearVelocity(-r * 10);
}
void Player::UseWeapon(const WEAPON_FIRE &usage)
@@ -144,7 +143,7 @@ void Player::Respawn(Oyster::Math::Float3 spawnPoint)
this->life = 100;
this->playerState = PLAYER_STATE::PLAYER_STATE_IDLE;
this->lookDir = Oyster::Math::Float4(1,0,0);
- this->newPhysicsState.SetCenterPosition(spawnPoint);
+ //this->newPhysicsState.centerPos = spawnPoint;
}
void Player::Rotate(const Oyster::Math3D::Float4 lookDir)
@@ -161,8 +160,8 @@ void Player::Rotate(const Oyster::Math3D::Float4 lookDir)
void Player::Jump()
{
- Oyster::Math::Float3 up = currPhysicsState.GetOrientation().v[1];
- newPhysicsState.ApplyLinearImpulse(up * MOVE_FORCE * this->gameInstance->GetFrameTime());
+ Oyster::Math::Float3 up = this->rigidBody->GetState().GetOrientation().v[1];
+ //newPhysicsState.ApplyLinearImpulse(up * MOVE_FORCE * this->gameInstance->GetFrameTime());
}
bool Player::IsWalking()
@@ -180,11 +179,11 @@ bool Player::IsIdle()
Oyster::Math::Float3 Player::GetPosition() const
{
- return (Oyster::Math::Float3)currPhysicsState.GetCenterPosition();
+ return (Oyster::Math::Float3) this->rigidBody->GetState().centerPos;
}
Oyster::Math::Float4x4 Player::GetOrientation() const
{
- return this->currPhysicsState.GetOrientation();
+ return this->rigidBody->GetState().GetOrientation();
}
Oyster::Math::Float3 Player::GetLookDir() const
{
diff --git a/Code/Game/GameLogic/StaticObject.cpp b/Code/Game/GameLogic/StaticObject.cpp
index c007b919..65cc0577 100644
--- a/Code/Game/GameLogic/StaticObject.cpp
+++ b/Code/Game/GameLogic/StaticObject.cpp
@@ -18,8 +18,8 @@ StaticObject::StaticObject(OBJECT_TYPE type)
StaticObject::StaticObject(Oyster::Physics::ICustomBody *rigidBody, OBJECT_TYPE type)
:Object(rigidBody,type)
{
- this->rigidBody->SetGravity(true);
- this->rigidBody->SetSubscription((Oyster::Physics::ICustomBody::EventAction_BeforeCollisionResponse)(CollisionManager::IgnoreCollision));
+ //this->rigidBody->SetGravity(true);
+ //this->rigidBody->SetSubscription((Oyster::Physics::ICustomBody::EventAction_BeforeCollisionResponse)(CollisionManager::IgnoreCollision));
}
StaticObject::StaticObject(void* collisionFuncBefore, void* collisionFuncAfter, OBJECT_TYPE type)
diff --git a/Code/Game/GameProtocols/LobbyProtocols.h b/Code/Game/GameProtocols/LobbyProtocols.h
index b57245ba..c821137b 100644
--- a/Code/Game/GameProtocols/LobbyProtocols.h
+++ b/Code/Game/GameProtocols/LobbyProtocols.h
@@ -312,6 +312,34 @@ namespace GameLogic
// private:
// Oyster::Network::CustomNetProtocol protocol;
//};
+
+ struct Protocol_LobbyClientReadyState :public Oyster::Network::CustomProtocolObject
+ {
+ bool isReady;
+
+ Protocol_LobbyClientReadyState()
+ {
+ this->protocol[0].value = protocol_Lobby_ClientReadyState;
+ this->protocol[0].type = Oyster::Network::NetAttributeType_Short;
+ this->protocol[1].type = Oyster::Network::NetAttributeType_Bool;
+ }
+ Protocol_LobbyClientReadyState(bool isReady)
+ {
+ this->isReady = isReady;
+ }
+ Protocol_LobbyClientReadyState(Oyster::Network::CustomNetProtocol& p)
+ {
+ this->isReady = p[1].value.netBool;
+ }
+ Oyster::Network::CustomNetProtocol GetProtocol() override
+ {
+ this->protocol[1].value = this->isReady;
+ return protocol;
+ }
+
+ private:
+ Oyster::Network::CustomNetProtocol protocol;
+ };
}
#endif // !GAMELOGIC_PLAYER_PROTOCOLS_H
diff --git a/Code/Game/GameProtocols/ObjectProtocols.h b/Code/Game/GameProtocols/ObjectProtocols.h
index 5ce10b27..753d61e3 100644
--- a/Code/Game/GameProtocols/ObjectProtocols.h
+++ b/Code/Game/GameProtocols/ObjectProtocols.h
@@ -1,3 +1,8 @@
+//////////////////////////////////////////////////////////
+// Created 2013 //
+// Dennis Andersen, Linda Andersson //
+//////////////////////////////////////////////////////////
+
#ifndef GAMELOGIC_OBJECT_PROTOCOLS_H
#define GAMELOGIC_OBJECT_PROTOCOLS_H
@@ -6,6 +11,7 @@
namespace GameLogic
{
+ //#define protocol_Gameplay_ObjectPickup 350
struct Protocol_ObjectPickup :public Oyster::Network::CustomProtocolObject
{
short object_ID;
@@ -50,10 +56,11 @@ namespace GameLogic
Oyster::Network::CustomNetProtocol protocol;
};
+ //#define protocol_Gameplay_ObjectDamage 351
struct Protocol_ObjectDamage :public Oyster::Network::CustomProtocolObject
{
int object_ID;
- float health; //Precentage%
+ float healthLost; //Precentage%
Protocol_ObjectDamage()
{
@@ -64,7 +71,7 @@ namespace GameLogic
this->protocol[2].type = Oyster::Network::NetAttributeType_Float;
object_ID = -1;
- health = 0.0f;
+ healthLost = 0.0f;
}
Protocol_ObjectDamage(Oyster::Network::CustomNetProtocol& p)
{
@@ -78,12 +85,12 @@ namespace GameLogic
this->protocol[2].type = Oyster::Network::NetAttributeType_Float;
object_ID = id;
- health = hp;
+ healthLost = hp;
}
Oyster::Network::CustomNetProtocol GetProtocol() override
{
this->protocol[1].value = object_ID;
- this->protocol[2].value = health;
+ this->protocol[2].value = healthLost;
return protocol;
}
@@ -91,51 +98,89 @@ namespace GameLogic
Oyster::Network::CustomNetProtocol protocol;
};
+ //#define protocol_Gameplay_ObjectHealthStatus 352
+ struct Protocol_ObjectHealthStatus :public Oyster::Network::CustomProtocolObject
+ {
+ float currentHealth;
+ int id;
+
+ Protocol_ObjectHealthStatus()
+ {
+ this->protocol[0].type = Oyster::Network::NetAttributeType_Short;
+ this->protocol[0].value.netShort = protocol_Gameplay_ObjectHealthStatus;
+ this->protocol[1].type = Oyster::Network::NetAttributeType_Int;
+ this->protocol[2].type = Oyster::Network::NetAttributeType_Float;
+ this->id = 0;
+ this->currentHealth = 0.0f;
+ }
+ Protocol_ObjectHealthStatus(int id, float health)
+ {
+ this->protocol[0].type = Oyster::Network::NetAttributeType_Short;
+ this->protocol[0].value.netShort = protocol_Gameplay_ObjectHealthStatus;
+ this->protocol[1].type = Oyster::Network::NetAttributeType_Int;
+ this->protocol[2].type = Oyster::Network::NetAttributeType_Float;
+ this->id = id; this->currentHealth = health;
+ }
+ Protocol_ObjectHealthStatus(Oyster::Network::CustomNetProtocol& p)
+ {
+ this->id = p[1].value.netInt;
+ this->currentHealth = p[2].value.netFloat;
+ }
+ Oyster::Network::CustomNetProtocol GetProtocol() override
+ {
+ this->protocol[1].value = this->id;
+ this->protocol[2].value = this->currentHealth;
+
+ return protocol;
+ }
+
+ private:
+ Oyster::Network::CustomNetProtocol protocol;
+ };
+
+ //#define protocol_Gameplay_ObjectPosition 353
struct Protocol_ObjectPosition :public Oyster::Network::CustomProtocolObject
{
- int object_ID;
- float worldMatrix[16];
-
+ short object_ID;
+ float position[3];
+
Protocol_ObjectPosition()
{
this->protocol[0].value = protocol_Gameplay_ObjectPosition;
- this->protocol[0].type = Oyster::Network::NetAttributeType_Short;
-
- this->protocol[1].type = Oyster::Network::NetAttributeType_Int;
+ this->protocol[0].type = Oyster::Network::NetAttributeType_Short;
+ this->protocol[1].type = Oyster::Network::NetAttributeType_Short;
+ this->protocol[2].type = Oyster::Network::NetAttributeType_Float;
+ this->protocol[3].type = Oyster::Network::NetAttributeType_Float;
+ this->protocol[4].type = Oyster::Network::NetAttributeType_Float;
- for (int i = 2; i <= 17; i++)
- {
- this->protocol[i].type = Oyster::Network::NetAttributeType_Float;
- }
- object_ID = -1;
- memset(&worldMatrix[0], 0, sizeof(float) * 16);
+ object_ID = 0;
+ memset(&position[0], 0, sizeof(float) * 3);
}
Protocol_ObjectPosition(Oyster::Network::CustomNetProtocol& p)
{
-
+ object_ID = p[1].value.netShort;
+ position[0] = p[2].value.netFloat;
+ position[1] = p[3].value.netFloat;
+ position[2] = p[4].value.netFloat;
}
- Protocol_ObjectPosition(float m[16], int id)
+ Protocol_ObjectPosition(float v[3], int id)
{
this->protocol[0].value = protocol_Gameplay_ObjectPosition;
this->protocol[0].type = Oyster::Network::NetAttributeType_Short;
-
- this->protocol[1].type = Oyster::Network::NetAttributeType_Int;
-
- for (int i = 2; i <= 17; i++)
- {
- this->protocol[i].type = Oyster::Network::NetAttributeType_Float;
- }
+ this->protocol[1].type = Oyster::Network::NetAttributeType_Short;
+ this->protocol[2].type = Oyster::Network::NetAttributeType_Float;
+ this->protocol[3].type = Oyster::Network::NetAttributeType_Float;
+ this->protocol[4].type = Oyster::Network::NetAttributeType_Float;
object_ID = id;
- memcpy(&worldMatrix[0], &m[0], sizeof(float)*16);
+ memcpy(&position[0], &v[0], sizeof(float) * 3);
}
Oyster::Network::CustomNetProtocol GetProtocol() override
{
this->protocol[1].value = object_ID;
- for (int i = 2; i <= 17; i++)
- {
- this->protocol[i].value = worldMatrix[i-2];
- }
+ this->protocol[2].value = position[0];
+ this->protocol[3].value = position[1];
+ this->protocol[4].value = position[2];
return protocol;
}
@@ -143,49 +188,202 @@ namespace GameLogic
Oyster::Network::CustomNetProtocol protocol;
};
+ //#define protocol_Gameplay_ObjectScale 354
+ struct Protocol_ObjectScale :public Oyster::Network::CustomProtocolObject
+ {
+ short object_ID;
+ float position[3];
+
+ Protocol_ObjectScale()
+ {
+ this->protocol[0].value = protocol_Gameplay_ObjectScale;
+ this->protocol[0].type = Oyster::Network::NetAttributeType_Short;
+ this->protocol[1].type = Oyster::Network::NetAttributeType_Short;
+ this->protocol[2].type = Oyster::Network::NetAttributeType_Float;
+ this->protocol[3].type = Oyster::Network::NetAttributeType_Float;
+ this->protocol[4].type = Oyster::Network::NetAttributeType_Float;
+
+ object_ID = 0;
+ memset(&position[0], 0, sizeof(float) * 3);
+ }
+ Protocol_ObjectScale(Oyster::Network::CustomNetProtocol& p)
+ {
+ object_ID = p[1].value.netShort;
+ position[0] = p[2].value.netFloat;
+ position[1] = p[3].value.netFloat;
+ position[2] = p[4].value.netFloat;
+ }
+ Protocol_ObjectScale(float v[3], int id)
+ {
+ this->protocol[0].value = protocol_Gameplay_ObjectScale;
+ this->protocol[0].type = Oyster::Network::NetAttributeType_Short;
+ this->protocol[1].type = Oyster::Network::NetAttributeType_Short;
+ this->protocol[2].type = Oyster::Network::NetAttributeType_Float;
+ this->protocol[3].type = Oyster::Network::NetAttributeType_Float;
+ this->protocol[4].type = Oyster::Network::NetAttributeType_Float;
+
+ object_ID = id;
+ memcpy(&position[0], &v[0], sizeof(float) * 3);
+ }
+ Oyster::Network::CustomNetProtocol GetProtocol() override
+ {
+ this->protocol[1].value = object_ID;
+ this->protocol[2].value = position[0];
+ this->protocol[3].value = position[1];
+ this->protocol[4].value = position[2];
+ return protocol;
+ }
+
+ private:
+ Oyster::Network::CustomNetProtocol protocol;
+ };
+
+ //#define protocol_Gameplay_ObjectRotation 355
+ struct Protocol_ObjectRotation :public Oyster::Network::CustomProtocolObject
+ {
+ short object_ID;
+ float position[3];
+
+ Protocol_ObjectRotation()
+ {
+ this->protocol[0].value = protocol_Gameplay_ObjectRotation;
+ this->protocol[0].type = Oyster::Network::NetAttributeType_Short;
+ this->protocol[1].type = Oyster::Network::NetAttributeType_Short;
+ this->protocol[2].type = Oyster::Network::NetAttributeType_Float;
+ this->protocol[3].type = Oyster::Network::NetAttributeType_Float;
+ this->protocol[4].type = Oyster::Network::NetAttributeType_Float;
+
+ object_ID = 0;
+ memset(&position[0], 0, sizeof(float) * 3);
+ }
+ Protocol_ObjectRotation(Oyster::Network::CustomNetProtocol& p)
+ {
+ object_ID = p[1].value.netShort;
+ position[0] = p[2].value.netFloat;
+ position[1] = p[3].value.netFloat;
+ position[2] = p[4].value.netFloat;
+ }
+ Protocol_ObjectRotation(float v[3], int id)
+ {
+ this->protocol[0].value = protocol_Gameplay_ObjectRotation;
+ this->protocol[0].type = Oyster::Network::NetAttributeType_Short;
+ this->protocol[1].type = Oyster::Network::NetAttributeType_Short;
+ this->protocol[2].type = Oyster::Network::NetAttributeType_Float;
+ this->protocol[3].type = Oyster::Network::NetAttributeType_Float;
+ this->protocol[4].type = Oyster::Network::NetAttributeType_Float;
+
+ object_ID = id;
+ memcpy(&position[0], &v[0], sizeof(float) * 3);
+ }
+ Oyster::Network::CustomNetProtocol GetProtocol() override
+ {
+ this->protocol[1].value = object_ID;
+ this->protocol[2].value = position[0];
+ this->protocol[3].value = position[1];
+ this->protocol[4].value = position[2];
+ return protocol;
+ }
+
+ private:
+ Oyster::Network::CustomNetProtocol protocol;
+ };
+
+ struct Protocol_ObjectPositionRotation :public Oyster::Network::CustomProtocolObject
+ {
+ short object_ID;
+ float position[3];
+ float rotation[3];
+
+ Protocol_ObjectPositionRotation()
+ {
+ this->protocol[0].value = protocol_Gameplay_ObjectPositionRotation;
+ this->protocol[0].type = Oyster::Network::NetAttributeType_Short;
+ this->protocol[1].type = Oyster::Network::NetAttributeType_Short;
+ //POSITION
+ this->protocol[2].type = Oyster::Network::NetAttributeType_Float;
+ this->protocol[3].type = Oyster::Network::NetAttributeType_Float;
+ this->protocol[4].type = Oyster::Network::NetAttributeType_Float;
+ //ROTATION
+ this->protocol[5].type = Oyster::Network::NetAttributeType_Float;
+ this->protocol[6].type = Oyster::Network::NetAttributeType_Float;
+ this->protocol[7].type = Oyster::Network::NetAttributeType_Float;
+
+ this->object_ID = 0;
+ memset(&this->position[0], 0, sizeof(float) * 3);
+ memset(&this->rotation[0], 0, sizeof(float) * 3);
+ }
+ Protocol_ObjectPositionRotation(Oyster::Network::CustomNetProtocol& p)
+ {
+ this->object_ID = p[1].value.netShort;
+ //POSITION
+ this->position[0] = p[2].value.netFloat;
+ this->position[1] = p[3].value.netFloat;
+ this->position[2] = p[4].value.netFloat;
+ //ROTATION
+ this->rotation[0] = p[5].value.netFloat;
+ this->rotation[1] = p[6].value.netFloat;
+ this->rotation[2] = p[7].value.netFloat;
+ }
+ Protocol_ObjectPositionRotation(float p[3], float r[3], int id)
+ {
+ this->protocol[0].value = protocol_Gameplay_ObjectPositionRotation;
+ this->protocol[0].type = Oyster::Network::NetAttributeType_Short;
+ this->protocol[1].type = Oyster::Network::NetAttributeType_Short;
+ //POSITION
+ this->protocol[2].type = Oyster::Network::NetAttributeType_Float;
+ this->protocol[3].type = Oyster::Network::NetAttributeType_Float;
+ this->protocol[4].type = Oyster::Network::NetAttributeType_Float;
+ //ROTATION
+ this->protocol[5].type = Oyster::Network::NetAttributeType_Float;
+ this->protocol[6].type = Oyster::Network::NetAttributeType_Float;
+ this->protocol[7].type = Oyster::Network::NetAttributeType_Float;
+
+ object_ID = id;
+ memcpy(&this->position[0], &p[0], sizeof(float) * 3);
+ memcpy(&this->rotation[0], &r[0], sizeof(float) * 3);
+ }
+ Oyster::Network::CustomNetProtocol GetProtocol() override
+ {
+ this->protocol[1].value = this->object_ID;
+ this->protocol[2].value = this->position[0];
+ this->protocol[3].value = this->position[1];
+ this->protocol[4].value = this->position[2];
+ this->protocol[5].value = this->rotation[0];
+ this->protocol[6].value = this->rotation[1];
+ this->protocol[7].value = this->rotation[2];
+ return protocol;
+ }
+
+ private:
+ Oyster::Network::CustomNetProtocol protocol;
+ };
+
+ //#define protocol_Gameplay_ObjectEnabled 356
struct Protocol_ObjectEnable :public Oyster::Network::CustomProtocolObject
{
- int object_ID;
- float worldMatrix[16];
+ int objectID;
Protocol_ObjectEnable()
{
this->protocol[0].value = protocol_Gameplay_ObjectEnabled;
- this->protocol[0].type = Oyster::Network::NetAttributeType_Short;
-
+ this->protocol[0].type = Oyster::Network::NetAttributeType_Short;
this->protocol[1].type = Oyster::Network::NetAttributeType_Int;
-
- for (int i = 2; i <= 17; i++)
- {
- this->protocol[i].type = Oyster::Network::NetAttributeType_Float;
- }
- object_ID = -1;
- memset(&worldMatrix[0], 0, sizeof(float) * 16);
+ this->objectID = -1;
+ }
+ Protocol_ObjectEnable(int objectID)
+ {
+ this->protocol[0].value = protocol_Gameplay_ObjectEnabled;
+ this->protocol[0].type = Oyster::Network::NetAttributeType_Short;
+ this->protocol[1].type = Oyster::Network::NetAttributeType_Int;
+ this->objectID = objectID;
}
Protocol_ObjectEnable(Oyster::Network::CustomNetProtocol& p)
{
-
- }
- Protocol_ObjectEnable(float m[16], int id)
- {
- this->protocol[0].value = protocol_Gameplay_ObjectEnabled;
- this->protocol[0].type = Oyster::Network::NetAttributeType_Short;
-
- this->protocol[1].type = Oyster::Network::NetAttributeType_Int;
-
- for (int i = 2; i <= 17; i++)
- { this->protocol[i].type = Oyster::Network::NetAttributeType_Float; }
-
- object_ID = id;
- memcpy(&worldMatrix[0], &m[0], sizeof(float)*16);
+ this->objectID = p[1].value.netInt;
}
Oyster::Network::CustomNetProtocol GetProtocol() override
{
- this->protocol[1].value = object_ID;
- for (int i = 2; i <= 17; i++)
- {
- this->protocol[i].value = worldMatrix[i-2];
- }
+ this->protocol[1].value = this->objectID;
return protocol;
}
@@ -193,38 +391,39 @@ namespace GameLogic
Oyster::Network::CustomNetProtocol protocol;
};
+ //#define protocol_Gameplay_ObjectDisabled 357
struct Protocol_ObjectDisable :public Oyster::Network::CustomProtocolObject
{
- int object_ID;
- float timer;
+ int objectID;
+ float seconds;
Protocol_ObjectDisable()
{
this->protocol[0].value = protocol_Gameplay_ObjectDisabled;
this->protocol[0].type = Oyster::Network::NetAttributeType_Short;
-
this->protocol[1].type = Oyster::Network::NetAttributeType_Int;
this->protocol[2].type = Oyster::Network::NetAttributeType_Float;
+ this->objectID = 0;
+ this->seconds = 0.0f;
}
- Protocol_ObjectDisable(Oyster::Network::CustomNetProtocol& p)
- {
-
- }
- Protocol_ObjectDisable(int id, float time)
+ Protocol_ObjectDisable(int objctID, float seconds)
{
this->protocol[0].value = protocol_Gameplay_ObjectDisabled;
this->protocol[0].type = Oyster::Network::NetAttributeType_Short;
-
this->protocol[1].type = Oyster::Network::NetAttributeType_Int;
this->protocol[2].type = Oyster::Network::NetAttributeType_Float;
-
- object_ID = id;
- timer = time;
+ this->objectID = objctID;
+ this->seconds = seconds;
+ }
+ Protocol_ObjectDisable(Oyster::Network::CustomNetProtocol& p)
+ {
+ this->objectID = p[1].value.netInt;
+ this->seconds = p[2].value.netFloat;
}
Oyster::Network::CustomNetProtocol GetProtocol() override
{
- this->protocol[1].value = object_ID;
- this->protocol[2].value = timer;
+ this->protocol[1].value = this->objectID;
+ this->protocol[2].value = this->seconds;
return protocol;
}
@@ -232,6 +431,7 @@ namespace GameLogic
Oyster::Network::CustomNetProtocol protocol;
};
+ //#define protocol_Gameplay_ObjectCreate 358
struct Protocol_ObjectCreate :public Oyster::Network::CustomProtocolObject
{
//ObjectType type; //ie player, box or whatever
@@ -304,6 +504,330 @@ namespace GameLogic
private:
Oyster::Network::CustomNetProtocol protocol;
};
+
+ //#define protocol_Gameplay_ObjectCreatePlayer 359
+ struct Protocol_ObjectCreatePlayer :public Oyster::Network::CustomProtocolObject
+ {
+ //ObjectType type; //ie player, box or whatever
+ int object_ID;
+ int teamId;
+ std::string name;
+ std::string meshName;
+ float position[3];
+ float rotation[3];
+ float scale[3];
+
+ Protocol_ObjectCreatePlayer()
+ {
+ this->protocol[0].value = protocol_Gameplay_ObjectCreatePlayer;
+ this->protocol[0].type = Oyster::Network::NetAttributeType_Short;
+
+ //PLAYER_ID
+ this->protocol[1].type = Oyster::Network::NetAttributeType_Int;
+ //TEAM_ID
+ this->protocol[2].type = Oyster::Network::NetAttributeType_Int;
+ //PLAYER-NAME
+ this->protocol[3].type = Oyster::Network::NetAttributeType_CharArray;
+ //MESH-NAME
+ this->protocol[4].type = Oyster::Network::NetAttributeType_CharArray;
+ //POSITION
+ this->protocol[5].type = Oyster::Network::NetAttributeType_Float;
+ this->protocol[6].type = Oyster::Network::NetAttributeType_Float;
+ this->protocol[7].type = Oyster::Network::NetAttributeType_Float;
+ //ROTATION
+ this->protocol[8].type = Oyster::Network::NetAttributeType_Float;
+ this->protocol[9].type = Oyster::Network::NetAttributeType_Float;
+ this->protocol[10].type = Oyster::Network::NetAttributeType_Float;
+ //SCALE
+ this->protocol[11].type = Oyster::Network::NetAttributeType_Float;
+ this->protocol[12].type = Oyster::Network::NetAttributeType_Float;
+ this->protocol[13].type = Oyster::Network::NetAttributeType_Float;
+ }
+ Protocol_ObjectCreatePlayer(Oyster::Network::CustomNetProtocol& p)
+ {
+
+ }
+ Protocol_ObjectCreatePlayer(float position[3], float rotation[3], float scale[3], int ObjectID, int teamID, std::string name, std::string meshName)
+ {
+ this->protocol[0].value = protocol_Gameplay_ObjectCreatePlayer;
+ this->protocol[0].type = Oyster::Network::NetAttributeType_Short;
+
+ //PLAYER_ID
+ this->protocol[1].type = Oyster::Network::NetAttributeType_Int;
+ //TEAM_ID
+ this->protocol[2].type = Oyster::Network::NetAttributeType_Int;
+ //PLAYER-NAME
+ this->protocol[3].type = Oyster::Network::NetAttributeType_CharArray;
+ //MESH-NAME
+ this->protocol[4].type = Oyster::Network::NetAttributeType_CharArray;
+ //POSITION
+ this->protocol[5].type = Oyster::Network::NetAttributeType_Float;
+ this->protocol[6].type = Oyster::Network::NetAttributeType_Float;
+ this->protocol[7].type = Oyster::Network::NetAttributeType_Float;
+ //ROTATION
+ this->protocol[8].type = Oyster::Network::NetAttributeType_Float;
+ this->protocol[9].type = Oyster::Network::NetAttributeType_Float;
+ this->protocol[10].type = Oyster::Network::NetAttributeType_Float;
+ //SCALE
+ this->protocol[11].type = Oyster::Network::NetAttributeType_Float;
+ this->protocol[12].type = Oyster::Network::NetAttributeType_Float;
+ this->protocol[13].type = Oyster::Network::NetAttributeType_Float;
+
+ this->object_ID = ObjectID;
+ this->teamId = teamID;
+ this->name = name;
+ this->meshName = meshName;
+ memcpy(&this->position[0], &position[0], sizeof(float)*3);
+ memcpy(&this->rotation[0], &rotation[0], sizeof(float)*3);
+ memcpy(&this->scale[0], &scale[0], sizeof(float)*3);
+ }
+ Oyster::Network::CustomNetProtocol GetProtocol() override
+ {
+
+ this->protocol[1].value = this->object_ID;
+ this->protocol[2].value = this->teamId;
+ this->protocol.Set(3, this->name);
+ this->protocol.Set(4, this->meshName);
+
+ //POSITION
+ this->protocol[5].value = this->position[0];
+ this->protocol[6].value = this->position[1];
+ this->protocol[7].value = this->position[2];
+ //ROTATION
+ this->protocol[8].value = this->rotation[0];
+ this->protocol[9].value = this->rotation[1];
+ this->protocol[10].value = this->rotation[2];
+ //SCALE
+ this->protocol[11].value = this->scale[0];
+ this->protocol[12].value = this->scale[1];
+ this->protocol[13].value = this->scale[2];
+
+ return protocol;
+ }
+
+ private:
+ Oyster::Network::CustomNetProtocol protocol;
+ };
+
+ //#define protocol_Gameplay_ObjectJoinTeam 360
+ struct Protocol_ObjectJoinTeam :public Oyster::Network::CustomProtocolObject
+ {
+ int objectID;
+ int teamID;
+
+ Protocol_ObjectJoinTeam()
+ {
+ this->protocol[0].type = Oyster::Network::NetAttributeType_Short;
+ this->protocol[0].value.netShort = protocol_Gameplay_ObjectJoinTeam;
+ this->protocol[1].type = Oyster::Network::NetAttributeType_Int;
+ this->protocol[2].type = Oyster::Network::NetAttributeType_Int;
+ this->objectID = 0;
+ this->teamID = 0;
+ }
+ Protocol_ObjectJoinTeam(int objID, int teamID)
+ {
+ this->protocol[0].type = Oyster::Network::NetAttributeType_Short;
+ this->protocol[0].value.netShort = protocol_Gameplay_ObjectJoinTeam;
+ this->protocol[1].type = Oyster::Network::NetAttributeType_Int;
+ this->protocol[2].type = Oyster::Network::NetAttributeType_Int;
+ this->objectID = objID;
+ this->teamID = teamID;
+ }
+ Protocol_ObjectJoinTeam(Oyster::Network::CustomNetProtocol& p)
+ {
+ this->objectID = p[1].value.netInt;
+ this->teamID = p[2].value.netInt;
+ }
+ Oyster::Network::CustomNetProtocol GetProtocol() override
+ {
+ this->protocol[1].value = this->objectID;
+ this->protocol[2].value = this->teamID;
+ return protocol;
+ }
+
+ private:
+ Oyster::Network::CustomNetProtocol protocol;
+ };
+
+ //#define protocol_Gameplay_ObjectLeaveTeam 361
+ struct Protocol_ObjectLeaveTeam :public Oyster::Network::CustomProtocolObject
+ {
+ int objectID;
+ Protocol_ObjectLeaveTeam()
+ {
+ this->protocol[0].type = Oyster::Network::NetAttributeType_Short;
+ this->protocol[0].value.netShort = protocol_Gameplay_ObjectLeaveTeam;
+ this->protocol[0].type = Oyster::Network::NetAttributeType_Int;
+ this->objectID = 0;
+ }
+ Protocol_ObjectLeaveTeam(int objectID)
+ {
+ this->protocol[0].type = Oyster::Network::NetAttributeType_Short;
+ this->protocol[0].value.netShort = protocol_Gameplay_ObjectLeaveTeam;
+ this->protocol[1].type = Oyster::Network::NetAttributeType_Int;
+ this->objectID = objectID;
+ }
+ Protocol_ObjectLeaveTeam(Oyster::Network::CustomNetProtocol& p)
+ {
+ this->objectID = p[1].value.netInt;
+ }
+ Oyster::Network::CustomNetProtocol GetProtocol() override
+ {
+ this->protocol[1].value = this->objectID;
+ return protocol;
+ }
+
+ private:
+ Oyster::Network::CustomNetProtocol protocol;
+ };
+
+ //#define protocol_Gameplay_ObjectWeaponCooldown 362
+ struct Protocol_ObjectWeaponCooldown :public Oyster::Network::CustomProtocolObject
+ {
+ float seconds;
+ Protocol_ObjectWeaponCooldown()
+ {
+ this->protocol[0].type = Oyster::Network::NetAttributeType_Short;
+ this->protocol[0].value.netShort = protocol_Gameplay_ObjectWeaponCooldown;
+ this->protocol[1].type = Oyster::Network::NetAttributeType_Float;
+ this->seconds = 0.0f;
+ }
+ Protocol_ObjectWeaponCooldown(float seconds)
+ {
+ this->protocol[0].type = Oyster::Network::NetAttributeType_Short;
+ this->protocol[0].value.netShort = protocol_Gameplay_ObjectWeaponCooldown;
+ this->protocol[1].type = Oyster::Network::NetAttributeType_Float;
+ this->seconds = seconds;
+ }
+ Protocol_ObjectWeaponCooldown(Oyster::Network::CustomNetProtocol& p)
+ {
+ this->seconds = p[1].value.netFloat;
+ }
+ Oyster::Network::CustomNetProtocol GetProtocol() override
+ {
+ this->protocol[1].value = this->seconds;
+ return protocol;
+ }
+
+ private:
+ Oyster::Network::CustomNetProtocol protocol;
+ };
+
+ //#define protocol_Gameplay_ObjectWeaponEnergy 363
+ struct Protocol_ObjectWeaponEnergy :public Oyster::Network::CustomProtocolObject
+ {
+ float energy;
+ Protocol_ObjectWeaponEnergy()
+ {
+ this->protocol[0].type = Oyster::Network::NetAttributeType_Short;
+ this->protocol[0].value.netShort = protocol_Gameplay_ObjectWeaponEnergy;
+ this->protocol[1].type = Oyster::Network::NetAttributeType_Float;
+ this->energy = 0.0f;
+ }
+ Protocol_ObjectWeaponEnergy(float energy)
+ {
+ this->protocol[0].type = Oyster::Network::NetAttributeType_Short;
+ this->protocol[0].value.netShort = protocol_Gameplay_ObjectWeaponEnergy;
+ this->protocol[1].type = Oyster::Network::NetAttributeType_Float;
+ this->energy = energy;
+ }
+ Protocol_ObjectWeaponEnergy(Oyster::Network::CustomNetProtocol& p)
+ {
+ this->energy = p[1].value.netFloat;
+ }
+ Oyster::Network::CustomNetProtocol GetProtocol() override
+ {
+ this->protocol[1].value = this->energy;
+ return protocol;
+ }
+
+ private:
+ Oyster::Network::CustomNetProtocol protocol;
+ };
+
+ //#define protocol_Gameplay_ObjectRespawn 364
+ struct Protocol_ObjectRespawn :public Oyster::Network::CustomProtocolObject
+ {
+ float position[3];
+
+ Protocol_ObjectRespawn()
+ {
+ this->protocol[0].type = Oyster::Network::NetAttributeType_Short;
+ this->protocol[0].value.netShort = protocol_Gameplay_ObjectRespawn;
+
+ this->protocol[1].type = Oyster::Network::NetAttributeType_Float;
+ this->protocol[2].type = Oyster::Network::NetAttributeType_Float;
+ this->protocol[3].type = Oyster::Network::NetAttributeType_Float;
+ memset(&this->position[0], 0, sizeof(float) * 3);
+ }
+ Protocol_ObjectRespawn(float position[3])
+ {
+ this->protocol[0].type = Oyster::Network::NetAttributeType_Short;
+ this->protocol[0].value.netShort = protocol_Gameplay_ObjectRespawn;
+ this->protocol[1].type = Oyster::Network::NetAttributeType_Float;
+ this->protocol[2].type = Oyster::Network::NetAttributeType_Float;
+ this->protocol[3].type = Oyster::Network::NetAttributeType_Float;
+
+ memcpy(&this->position[0], &position[0], sizeof(float) * 3);
+ }
+ Protocol_ObjectRespawn(Oyster::Network::CustomNetProtocol& p)
+ {
+ this->position[0] = p[1].value.netFloat;
+ this->position[1] = p[2].value.netFloat;
+ this->position[2] = p[3].value.netFloat;
+ }
+ Oyster::Network::CustomNetProtocol GetProtocol() override
+ {
+ this->protocol[1].value = this->position[0];
+ this->protocol[2].value = this->position[1];
+ this->protocol[3].value = this->position[2];
+ return protocol;
+ }
+
+ private:
+ Oyster::Network::CustomNetProtocol protocol;
+ };
+
+ //#define protocol_Gameplay_ObjectDie 365
+ struct Protocol_ObjectDie :public Oyster::Network::CustomProtocolObject
+ {
+ int objectID;
+ float seconds;
+
+ Protocol_ObjectDie()
+ {
+ this->protocol[0].type = Oyster::Network::NetAttributeType_Short;
+ this->protocol[0].value.netShort = protocol_Gameplay_ObjectDie;
+ this->protocol[1].type = Oyster::Network::NetAttributeType_Int;
+ this->protocol[2].type = Oyster::Network::NetAttributeType_Float;
+ this->objectID = 0;
+ this->seconds = 0.0f;
+ }
+ Protocol_ObjectDie(int objectID, float seconds)
+ {
+ this->protocol[0].type = Oyster::Network::NetAttributeType_Short;
+ this->protocol[0].value.netShort = protocol_Gameplay_ObjectDie;
+ this->protocol[1].type = Oyster::Network::NetAttributeType_Int;
+ this->protocol[2].type = Oyster::Network::NetAttributeType_Float;
+ this->objectID = objectID;
+ this->seconds = seconds;
+ }
+ Protocol_ObjectDie(Oyster::Network::CustomNetProtocol& p)
+ {
+ this->objectID = p[1].value.netInt;
+ this->seconds = p[2].value.netFloat;
+ }
+ Oyster::Network::CustomNetProtocol GetProtocol() override
+ {
+ this->protocol[1].value = this->objectID;
+ this->protocol[2].value = this->seconds;
+ return protocol;
+ }
+
+ private:
+ Oyster::Network::CustomNetProtocol protocol;
+ };
+
}
#endif // !GAMELOGIC_PLAYER_PROTOCOLS_H
\ No newline at end of file
diff --git a/Code/Game/GameProtocols/PlayerProtocols.h b/Code/Game/GameProtocols/PlayerProtocols.h
index 81e6fbb8..a3c3501e 100644
--- a/Code/Game/GameProtocols/PlayerProtocols.h
+++ b/Code/Game/GameProtocols/PlayerProtocols.h
@@ -8,56 +8,67 @@
#include
#include "ProtocolIdentificationID.h"
-#include
-
-//protocol_Gameplay_PlayerMovement 300
-//protocol_Gameplay_PlayerMouseMovement 301
-//protocol_Gameplay_PlayerChangeWeapon 302
namespace GameLogic
{
- struct Protocol_PlayerMovement :public Oyster::Network::CustomProtocolObject
+ struct Protocol_PlayerMovementRight :public Oyster::Network::CustomProtocolObject
{
- bool bForward;
- bool bBackward;
- bool bLeft;
- bool bRight;
-
- Protocol_PlayerMovement()
+ Protocol_PlayerMovementRight()
{
- this->protocol[0].value = protocol_Gameplay_PlayerMovement;
+ this->protocol[0].value = protocol_Gameplay_PlayerMovementRight;
this->protocol[0].type = Oyster::Network::NetAttributeType_Short;
-
- this->protocol[1].type = Oyster::Network::NetAttributeType_Bool;
- this->protocol[2].type = Oyster::Network::NetAttributeType_Bool;
- this->protocol[3].type = Oyster::Network::NetAttributeType_Bool;
- this->protocol[4].type = Oyster::Network::NetAttributeType_Bool;
- }
- Protocol_PlayerMovement(Oyster::Network::CustomNetProtocol& p)
- {
- bForward = p[1].value.netBool;
- bBackward = p[2].value.netBool;
- bLeft = p[3].value.netBool;
- bRight = p[4].value.netBool;
- }
- const Protocol_PlayerMovement& operator=(Oyster::Network::CustomNetProtocol& val)
- {
- bForward = val[1].value.netBool;
- bBackward = val[2].value.netBool;
- bLeft = val[3].value.netBool;
- bRight = val[4].value.netBool;
-
- return *this;
}
Oyster::Network::CustomNetProtocol GetProtocol() override
- {
- this->protocol[1].value = bForward;
- this->protocol[2].value = bBackward;
- this->protocol[3].value = bLeft;
- this->protocol[4].value = bRight;
+ { return protocol; }
- return protocol;
+ private:
+ Oyster::Network::CustomNetProtocol protocol;
+ };
+ struct Protocol_PlayerMovementLeft :public Oyster::Network::CustomProtocolObject
+ {
+ Protocol_PlayerMovementLeft()
+ {
+ this->protocol[0].value = protocol_Gameplay_PlayerMovementLeft;
+ this->protocol[0].type = Oyster::Network::NetAttributeType_Short;
}
+ Oyster::Network::CustomNetProtocol GetProtocol() override { return protocol; }
+
+ private:
+ Oyster::Network::CustomNetProtocol protocol;
+ };
+ struct Protocol_PlayerMovementForward :public Oyster::Network::CustomProtocolObject
+ {
+ Protocol_PlayerMovementForward()
+ {
+ this->protocol[0].value = protocol_Gameplay_PlayerMovementForward;
+ this->protocol[0].type = Oyster::Network::NetAttributeType_Short;
+ }
+ Oyster::Network::CustomNetProtocol GetProtocol() override { return protocol; }
+
+ private:
+ Oyster::Network::CustomNetProtocol protocol;
+ };
+ struct Protocol_PlayerMovementBackward :public Oyster::Network::CustomProtocolObject
+ {
+ Protocol_PlayerMovementBackward()
+ {
+ this->protocol[0].value = protocol_Gameplay_PlayerMovementBackward;
+ this->protocol[0].type = Oyster::Network::NetAttributeType_Short;
+ }
+ Oyster::Network::CustomNetProtocol GetProtocol() override { return protocol; }
+
+ private:
+ Oyster::Network::CustomNetProtocol protocol;
+ };
+
+ struct Protocol_PlayerJump :public Oyster::Network::CustomProtocolObject
+ {
+ Protocol_PlayerJump()
+ {
+ this->protocol[0].value = protocol_Gameplay_PlayerJump;
+ this->protocol[0].type = Oyster::Network::NetAttributeType_Short;
+ }
+ Oyster::Network::CustomNetProtocol GetProtocol() override { return protocol; }
private:
Oyster::Network::CustomNetProtocol protocol;
@@ -65,7 +76,6 @@ namespace GameLogic
struct Protocol_PlayerLook :public Oyster::Network::CustomProtocolObject
{
-
float lookDirX;
float lookDirY;
float lookDirZ;
@@ -180,35 +190,6 @@ namespace GameLogic
Oyster::Network::CustomNetProtocol protocol;
};
- struct Protocol_PlayerJump :public Oyster::Network::CustomProtocolObject
- {
- bool hasJumped;
-
- Protocol_PlayerJump()
- {
- this->protocol[0].value = protocol_Gameplay_PlayerJump;
- this->protocol[0].type = Oyster::Network::NetAttributeType_Short;
-
- this->protocol[1].type = Oyster::Network::NetAttributeType_Bool;
- }
- Protocol_PlayerJump(Oyster::Network::CustomNetProtocol& p)
- {
- hasJumped = p[1].value.netBool;
- }
- const Protocol_PlayerJump& operator=(Oyster::Network::CustomNetProtocol& val)
- {
- hasJumped = val[1].value.netBool;
- return *this;
- }
- Oyster::Network::CustomNetProtocol GetProtocol() override
- {
- this->protocol[1].value = hasJumped;
- return protocol;
- }
-
- private:
- Oyster::Network::CustomNetProtocol protocol;
- };
}
#endif // !GAMELOGIC_PLAYER_PROTOCOLS_H
diff --git a/Code/Game/GameProtocols/ProtocolIdentificationID.h b/Code/Game/GameProtocols/ProtocolIdentificationID.h
index cb596a1c..62d0983e 100644
--- a/Code/Game/GameProtocols/ProtocolIdentificationID.h
+++ b/Code/Game/GameProtocols/ProtocolIdentificationID.h
@@ -34,6 +34,7 @@
#define protocol_Lobby_Refresh 204
#define protocol_Lobby_ClientData 205
#define protocol_Lobby_GameData 206
+#define protocol_Lobby_ClientReadyState 207
#define protocol_LobbyMAX 299
@@ -41,17 +42,32 @@
/********* GAMEPLAY PROTOCOLS ***************************************************************************************************/
/***********[ 300 - 399 ]***********/
#define protocol_GameplayMIN 300
-#define protocol_Gameplay_PlayerMovement 300
-#define protocol_Gameplay_PlayerLookDir 301
-#define protocol_Gameplay_PlayerChangeWeapon 302
-#define protocol_Gameplay_PlayerShot 303
-#define protocol_Gameplay_PlayerJump 304
-#define protocol_Gameplay_ObjectPickup 305
-#define protocol_Gameplay_ObjectDamage 306
-#define protocol_Gameplay_ObjectPosition 307
-#define protocol_Gameplay_ObjectEnabled 308
-#define protocol_Gameplay_ObjectDisabled 309
-#define protocol_Gameplay_ObjectCreate 310
+#define protocol_Gameplay_PlayerMovementRight 300
+#define protocol_Gameplay_PlayerMovementLeft 301
+#define protocol_Gameplay_PlayerMovementForward 302
+#define protocol_Gameplay_PlayerMovementBackward 303
+#define protocol_Gameplay_PlayerLookDir 304
+#define protocol_Gameplay_PlayerChangeWeapon 305
+#define protocol_Gameplay_PlayerShot 306
+#define protocol_Gameplay_PlayerJump 307
+
+#define protocol_Gameplay_ObjectPickup 350
+#define protocol_Gameplay_ObjectDamage 351
+#define protocol_Gameplay_ObjectHealthStatus 352
+#define protocol_Gameplay_ObjectPosition 353
+#define protocol_Gameplay_ObjectScale 354
+#define protocol_Gameplay_ObjectRotation 355
+#define protocol_Gameplay_ObjectPositionRotation 356
+#define protocol_Gameplay_ObjectEnabled 357
+#define protocol_Gameplay_ObjectDisabled 358
+#define protocol_Gameplay_ObjectCreate 359
+#define protocol_Gameplay_ObjectCreatePlayer 360
+#define protocol_Gameplay_ObjectJoinTeam 361
+#define protocol_Gameplay_ObjectLeaveTeam 362
+#define protocol_Gameplay_ObjectWeaponCooldown 363
+#define protocol_Gameplay_ObjectWeaponEnergy 364
+#define protocol_Gameplay_ObjectRespawn 365
+#define protocol_Gameplay_ObjectDie 366
#define protocol_GameplayMAX 399
diff --git a/Code/Game/GameServer/GameLobby.h b/Code/Game/GameServer/GameLobby.h
index 94cb0e3c..5a996e63 100644
--- a/Code/Game/GameServer/GameLobby.h
+++ b/Code/Game/GameServer/GameLobby.h
@@ -9,6 +9,7 @@
#include
#include
#include "GameSession.h"
+#include
namespace DanBias
{
@@ -44,6 +45,7 @@ namespace DanBias
void LobbyRefresh(GameLogic::Protocol_LobbyRefresh& p, Oyster::Network::NetworkClient* c); //id = protocol_Lobby_Refresh:
void LobbyGameData(GameLogic::Protocol_LobbyGameData& p, Oyster::Network::NetworkClient* c); //id = protocol_Lobby_GameData:
void LobbyMainData(GameLogic::Protocol_LobbyClientData& p, Oyster::Network::NetworkClient* c); //id = protocol_Lobby_MainData:
+ void LobbyReady(GameLogic::Protocol_LobbyClientReadyState& p, Oyster::Network::NetworkClient* c); //id = protocol_Lobby_ClientReadyState:
private:
void ClientEventCallback(Oyster::Network::NetEvent e) override;
@@ -52,10 +54,11 @@ namespace DanBias
private:
Utility::WinTimer timer;
float refreshFrequency;
-
+ Utility::DynamicMemory::LinkedList readyList;
GameSession gameSession;
LobbyLevelData description;
Utility::DynamicMemory::SmartPointer sessionOwner;
+
};
}//End namespace DanBias
#endif // !DANBIASGAME_GAMELOBBY_H
diff --git a/Code/Game/GameServer/GameSession.h b/Code/Game/GameServer/GameSession.h
index b7980605..3d86ea78 100644
--- a/Code/Game/GameServer/GameSession.h
+++ b/Code/Game/GameServer/GameSession.h
@@ -75,11 +75,14 @@ namespace DanBias
private:
void ParseProtocol ( Oyster::Network::CustomNetProtocol& p, DanBias::GameClient* c );
- void Gameplay_PlayerMovement ( GameLogic::Protocol_PlayerMovement& p, DanBias::GameClient* c );
+ void Gameplay_PlayerMovementRight ( DanBias::GameClient* c );
+ void Gameplay_PlayerMovementLeft ( DanBias::GameClient* c );
+ void Gameplay_PlayerMovementBack ( DanBias::GameClient* c );
+ void Gameplay_PlayerMovementForth ( DanBias::GameClient* c );
+ void Gameplay_PlayerJump ( DanBias::GameClient* c );
void Gameplay_PlayerLookDir ( GameLogic::Protocol_PlayerLook& p, DanBias::GameClient* c );
void Gameplay_PlayerChangeWeapon ( GameLogic::Protocol_PlayerChangeWeapon& p, DanBias::GameClient* c );
void Gameplay_PlayerShot ( GameLogic::Protocol_PlayerShot& p, DanBias::GameClient* c );
- void Gameplay_PlayerJump ( GameLogic::Protocol_PlayerJump& p, DanBias::GameClient* c );
void Gameplay_ObjectPickup ( GameLogic::Protocol_ObjectPickup& p, DanBias::GameClient* c );
void Gameplay_ObjectDamage ( GameLogic::Protocol_ObjectDamage& p, DanBias::GameClient* c );
void Gameplay_ObjectPosition ( GameLogic::Protocol_ObjectPosition& p, DanBias::GameClient* c );
@@ -88,7 +91,7 @@ namespace DanBias
void Gameplay_ObjectCreate ( GameLogic::Protocol_ObjectCreate& p, DanBias::GameClient* c );
void General_Status ( GameLogic::Protocol_General_Status& p, DanBias::GameClient* c );
void General_Text ( GameLogic::Protocol_General_Text& p, DanBias::GameClient* c );
-
+
//Callback method recieving from gamelogic
static void ObjectMove ( GameLogic::IObjectData* movedObject );
static void ObjectDisabled ( GameLogic::IObjectData* movedObject, float seconds );
diff --git a/Code/Game/GameServer/Implementation/GameLobby.cpp b/Code/Game/GameServer/Implementation/GameLobby.cpp
index e88da318..4c08a2f2 100644
--- a/Code/Game/GameServer/Implementation/GameLobby.cpp
+++ b/Code/Game/GameServer/Implementation/GameLobby.cpp
@@ -47,27 +47,35 @@ namespace DanBias
}
bool GameLobby::StartGameSession( )
{
- GameSession::GameDescription desc;
- desc.maxClients = this->description.maxClients;
- desc.gameMode = this->description.gameMode;
- desc.gameTime = this->description.gameTime;
- desc.mapNumber = this->description.mapNumber;
- desc.owner = this;
- desc.clients = this->clients;
-
- if(desc.gameTime == 0.0f)
- desc.gameTime = (60.0f * 10.0f); //note: Default game time length should be fetched from somewhere.
-
- if(desc.maxClients == 0)
- desc.maxClients = 10; //note: Default should be fetched somewhere else..
-
- this->clients.Clear(); //Remove clients from lobby list
-
- if(this->gameSession.Create(desc))
+ //Check if all clients is ready
+ if(this->GetClientCount() == this->readyList.Size())
{
- this->gameSession.Run();
+ GameSession::GameDescription desc;
+ desc.maxClients = this->description.maxClients;
+ desc.gameMode = this->description.gameMode;
+ desc.gameTime = this->description.gameTime;
+ desc.mapNumber = this->description.mapNumber;
+ desc.owner = this;
+ desc.clients = this->clients;
- return true;
+ if(desc.gameTime == 0.0f)
+ desc.gameTime = (int)(60.0f * 10.0f); //note: Default game time length should be fetched from somewhere.
+
+ if(desc.maxClients == 0)
+ desc.maxClients = 10; //note: Default should be fetched somewhere else..
+
+ this->clients.Clear(); //Remove clients from lobby list
+
+ if(this->gameSession.Create(desc))
+ {
+ this->gameSession.Run();
+
+ return true;
+ }
+ }
+ else
+ {
+ //?
}
return false;
}
@@ -77,12 +85,16 @@ namespace DanBias
switch (e.args.type)
{
case NetworkClient::ClientEventArgs::EventType_Disconnect:
+
break;
case NetworkClient::ClientEventArgs::EventType_ProtocolFailedToRecieve:
+
break;
case NetworkClient::ClientEventArgs::EventType_ProtocolFailedToSend:
printf("\t(%i : %s) - EventType_ProtocolFailedToSend\n", e.sender->GetID(), e.sender->GetIpAddress().c_str());
e.sender->Disconnect();
+ this->readyList.Remove(e.sender);
+ this->clients.Remove(e.sender);
break;
case NetworkClient::ClientEventArgs::EventType_ProtocolRecieved:
printf("\t(%i : %s) - EventType_ProtocolRecieved\n", e.sender->GetID(), e.sender->GetIpAddress().c_str());
diff --git a/Code/Game/GameServer/Implementation/GameLobby_ProtocolParser.cpp b/Code/Game/GameServer/Implementation/GameLobby_ProtocolParser.cpp
index 93986650..35f6f4ee 100644
--- a/Code/Game/GameServer/Implementation/GameLobby_ProtocolParser.cpp
+++ b/Code/Game/GameServer/Implementation/GameLobby_ProtocolParser.cpp
@@ -9,26 +9,26 @@ void GameLobby::ParseProtocol(Oyster::Network::CustomNetProtocol& p, NetworkClie
{
switch (p[0].value.netShort)
{
- case protocol_General_Status: this->GeneralStatus (Protocol_General_Status (p), c);
+ case protocol_General_Status: this->GeneralStatus (Protocol_General_Status (p), c);
break;
- case protocol_General_Text: this->GeneralText (Protocol_General_Text (p), c);
+ case protocol_General_Text: this->GeneralText (Protocol_General_Text (p), c);
break;
- //case protocol_Lobby_Create: this->LobbyCreateGame (Protocol_LobbyCreateGame (p), c);
+ //case protocol_Lobby_Create: this->LobbyCreateGame (Protocol_LobbyCreateGame (p), c);
//break;
- case protocol_Lobby_Start: this->LobbyStartGame (Protocol_LobbyStartGame (p), c);
+ case protocol_Lobby_Start: this->LobbyStartGame (Protocol_LobbyStartGame (p), c);
break;
- //case protocol_Lobby_Join: this->LobbyJoin (Protocol_LobbyJoin (p), c);
+ //case protocol_Lobby_Join: this->LobbyJoin (Protocol_LobbyJoin (p), c);
//break;
- case protocol_Lobby_Login: this->LobbyLogin (Protocol_LobbyLogin (p), c);
+ case protocol_Lobby_Login: this->LobbyLogin (Protocol_LobbyLogin (p), c);
break;
- case protocol_Lobby_Refresh: this->LobbyRefresh (Protocol_LobbyRefresh (p), c);
+ case protocol_Lobby_Refresh: this->LobbyRefresh (Protocol_LobbyRefresh (p), c);
break;
- case protocol_Lobby_GameData: this->LobbyGameData (Protocol_LobbyGameData (p), c);
+ case protocol_Lobby_GameData: this->LobbyGameData (Protocol_LobbyGameData (p), c);
break;
- case protocol_Lobby_ClientData: this->LobbyMainData (Protocol_LobbyClientData (p), c);
+ case protocol_Lobby_ClientData: this->LobbyMainData (Protocol_LobbyClientData (p), c);
+ break;
+ case protocol_Lobby_ClientReadyState: this->LobbyReady (Protocol_LobbyClientReadyState (p), c);
break;
- //case protocol_Lobby_GameData: this->LobbyGameData (Protocol_LobbyGameData (p), c);
- //break;
}
}
@@ -98,5 +98,15 @@ void GameLobby::LobbyMainData(GameLogic::Protocol_LobbyClientData& p, Oyster::Ne
{
}
-
+void GameLobby::LobbyReady(GameLogic::Protocol_LobbyClientReadyState& p, Oyster::Network::NetworkClient* c)
+{
+ if(p.isReady)
+ {
+ this->readyList.PushBack(c);
+ }
+ else
+ {
+ this->readyList.Remove(c);
+ }
+}
diff --git a/Code/Game/GameServer/Implementation/GameSession_Gameplay.cpp b/Code/Game/GameServer/Implementation/GameSession_Gameplay.cpp
index bbbfff62..e18fc810 100644
--- a/Code/Game/GameServer/Implementation/GameSession_Gameplay.cpp
+++ b/Code/Game/GameServer/Implementation/GameSession_Gameplay.cpp
@@ -85,7 +85,7 @@ namespace DanBias
void GameSession::ObjectMove(GameLogic::IObjectData* movedObject)
{
- float dt = (float)GameSession::gameSession->networkTimer.getElapsedSeconds();
+ //float dt = (float)GameSession::gameSession->networkTimer.getElapsedSeconds();
//Duh... This was causing alot of problems, it's in the wrong place...
//Need to figure out where to put this frame locker.
//We only need to send network packages when necessary, ie not 120 times per frame.
@@ -93,64 +93,13 @@ namespace DanBias
//graphics update (60 fps) on the client side. To send more than this would be lost
//bandwidth.
//if( dt >= GameSession::gameSession->networkFrameTime )
- {
- GameSession::gameSession->networkTimer.reset();
-
- GameLogic::IObjectData* obj = movedObject;
- if(movedObject->GetID() == testID) //TODO: TEST
- {
- float sec = (float)testTimer.getElapsedSeconds();
- sec = 0;
- }
-
- int id = obj->GetID();
- Protocol_ObjectPosition p(obj->GetOrientation(), id);
- //if(id != 1)
+ //{
+ // GameSession::gameSession->networkTimer.reset();
+ int id = movedObject->GetID();
+ //Protocol_ObjectPosition p(movedObject->GetPosition(), id);
+ Protocol_ObjectPositionRotation p(movedObject->GetPosition(), movedObject->GetRotation(), id);
GameSession::gameSession->Send(p.GetProtocol());
-
-
- /*
- if(dynamic_cast(obj))
- {
- obj = ((GameLogic::ILevelData*)movedObject)->GetObjectAt(0);
- if(obj)
- {
- if(obj->GetObjectType() == OBJECT_TYPE_WORLD)
- {
- int id = obj->GetID();
- Oyster::Math::Float4x4 world =obj->GetOrientation();
-
- Protocol_ObjectPosition p(world, id);
- gameSession->Send(p.GetProtocol());
- }
- }
-
- obj =((GameLogic::ILevelData*)movedObject)->GetObjectAt(1);
- if(obj)
- {
- if(obj->GetObjectType() == OBJECT_TYPE_BOX)
- {
- int id = obj->GetID();
- Oyster::Math::Float4x4 world = obj->GetOrientation();
- Protocol_ObjectPosition p(world, id);
- gameSession->Send(p.GetProtocol());
- }
- }
-
- obj =((GameLogic::ILevelData*)movedObject)->GetObjectAt(2);
- if(obj)
- {
- if(obj->GetObjectType() == OBJECT_TYPE_BOX)
- {
- int id = obj->GetID();
- Oyster::Math::Float4x4 world = obj->GetOrientation();
- Protocol_ObjectPosition p(world, id);
- GameSession::gameSession->Send(p.GetProtocol());
- }
- }
- }
- */
- }
+ //}
}
void GameSession::ObjectDisabled( GameLogic::IObjectData* movedObject, float seconds )
@@ -168,43 +117,64 @@ namespace DanBias
switch (p[0].value.netShort)
{
- case protocol_Gameplay_PlayerMovement: this->Gameplay_PlayerMovement ( Protocol_PlayerMovement (p), c );
+ case protocol_Gameplay_PlayerMovementBackward: this->Gameplay_PlayerMovementBack ( c );
break;
- case protocol_Gameplay_PlayerLookDir: this->Gameplay_PlayerLookDir ( Protocol_PlayerLook (p), c );
+ case protocol_Gameplay_PlayerMovementForward: this->Gameplay_PlayerMovementForth ( c );
break;
- case protocol_Gameplay_PlayerChangeWeapon: this->Gameplay_PlayerChangeWeapon ( Protocol_PlayerChangeWeapon (p), c );
+ case protocol_Gameplay_PlayerMovementLeft: this->Gameplay_PlayerMovementLeft ( c );
break;
- case protocol_Gameplay_PlayerShot: this->Gameplay_PlayerShot ( Protocol_PlayerShot (p), c );
+ case protocol_Gameplay_PlayerMovementRight: this->Gameplay_PlayerMovementRight ( c );
break;
- case protocol_Gameplay_PlayerJump: this->Gameplay_PlayerJump ( Protocol_PlayerJump (p), c );
+ case protocol_Gameplay_PlayerJump: this->Gameplay_PlayerJump ( c );
break;
- case protocol_Gameplay_ObjectPickup: this->Gameplay_ObjectPickup ( Protocol_ObjectPickup (p), c );
+ case protocol_Gameplay_PlayerLookDir: this->Gameplay_PlayerLookDir ( Protocol_PlayerLook (p), c );
break;
- case protocol_Gameplay_ObjectDamage: this->Gameplay_ObjectDamage ( Protocol_ObjectDamage (p), c );
+ case protocol_Gameplay_PlayerChangeWeapon: this->Gameplay_PlayerChangeWeapon ( Protocol_PlayerChangeWeapon (p), c );
break;
- case protocol_Gameplay_ObjectPosition: this->Gameplay_ObjectPosition ( Protocol_ObjectPosition (p), c );
+ case protocol_Gameplay_PlayerShot: this->Gameplay_PlayerShot ( Protocol_PlayerShot (p), c );
break;
- case protocol_Gameplay_ObjectEnabled: this->Gameplay_ObjectEnabled ( Protocol_ObjectEnable (p), c );
+
+ case protocol_Gameplay_ObjectPickup: this->Gameplay_ObjectPickup ( Protocol_ObjectPickup (p), c );
break;
- case protocol_Gameplay_ObjectDisabled: this->Gameplay_ObjectDisabled ( Protocol_ObjectDisable (p), c );
+ case protocol_Gameplay_ObjectDamage: this->Gameplay_ObjectDamage ( Protocol_ObjectDamage (p), c );
break;
- case protocol_Gameplay_ObjectCreate: this->Gameplay_ObjectCreate ( Protocol_ObjectCreate (p), c );
+ case protocol_Gameplay_ObjectPosition: this->Gameplay_ObjectPosition ( Protocol_ObjectPosition (p), c );
break;
- case protocol_General_Status: this->General_Status ( Protocol_General_Status (p), c );
+ case protocol_Gameplay_ObjectEnabled: this->Gameplay_ObjectEnabled ( Protocol_ObjectEnable (p), c );
break;
- case protocol_General_Text: this->General_Text ( Protocol_General_Text (p), c );
+ case protocol_Gameplay_ObjectDisabled: this->Gameplay_ObjectDisabled ( Protocol_ObjectDisable (p), c );
+ break;
+ case protocol_Gameplay_ObjectCreate: this->Gameplay_ObjectCreate ( Protocol_ObjectCreate (p), c );
+ break;
+
+ case protocol_General_Status: this->General_Status ( Protocol_General_Status (p), c );
+ break;
+ case protocol_General_Text: this->General_Text ( Protocol_General_Text (p), c );
break;
}
}
- void GameSession::Gameplay_PlayerMovement ( Protocol_PlayerMovement& p, DanBias::GameClient* c )
+ void GameSession::Gameplay_PlayerMovementBack ( DanBias::GameClient* c )
{
- if(p.bForward) c->GetPlayer()->Move(GameLogic::PLAYER_MOVEMENT_FORWARD);
- if(p.bBackward) c->GetPlayer()->Move(GameLogic::PLAYER_MOVEMENT_BACKWARD);
- if(p.bLeft) c->GetPlayer()->Move(GameLogic::PLAYER_MOVEMENT_LEFT);
- if(p.bRight) c->GetPlayer()->Move(GameLogic::PLAYER_MOVEMENT_RIGHT);
+ c->GetPlayer()->Move(GameLogic::PLAYER_MOVEMENT_BACKWARD);
}
- void GameSession::Gameplay_PlayerLookDir ( Protocol_PlayerLook& p, DanBias::GameClient* c )
+ void GameSession::Gameplay_PlayerMovementForth ( DanBias::GameClient* c )
+ {
+ c->GetPlayer()->Move(GameLogic::PLAYER_MOVEMENT_FORWARD);
+ }
+ void GameSession::Gameplay_PlayerMovementLeft ( DanBias::GameClient* c )
+ {
+ c->GetPlayer()->Move(GameLogic::PLAYER_MOVEMENT_LEFT);
+ }
+ void GameSession::Gameplay_PlayerMovementRight ( DanBias::GameClient* c )
+ {
+ c->GetPlayer()->Move(GameLogic::PLAYER_MOVEMENT_RIGHT);
+ }
+ void GameSession::Gameplay_PlayerJump ( DanBias::GameClient* c )
+ {
+ c->GetPlayer()->Move(GameLogic::PLAYER_MOVEMENT_JUMP);
+ }
+ void GameSession::Gameplay_PlayerLookDir ( Protocol_PlayerLook& p, DanBias::GameClient* c )
{
Oyster::Math3D::Float4 lookDir;
lookDir.x = p.lookDirX;
@@ -213,46 +183,44 @@ namespace DanBias
lookDir.w = p.deltaX;
c->GetPlayer()->Rotate(lookDir);
}
- void GameSession::Gameplay_PlayerChangeWeapon ( Protocol_PlayerChangeWeapon& p, DanBias::GameClient* c )
+ void GameSession::Gameplay_PlayerChangeWeapon ( Protocol_PlayerChangeWeapon& p, DanBias::GameClient* c )
{
}
- void GameSession::Gameplay_PlayerShot ( Protocol_PlayerShot& p, DanBias::GameClient* c )
+ void GameSession::Gameplay_PlayerShot ( Protocol_PlayerShot& p, DanBias::GameClient* c )
{
if(p.secondaryPressed) c->GetPlayer()->UseWeapon(GameLogic::WEAPON_USE_SECONDARY_PRESS);
if(p.primaryPressed) c->GetPlayer()->UseWeapon(GameLogic::WEAPON_USE_PRIMARY_PRESS);
if(p.utilityPressed) c->GetPlayer()->UseWeapon(GameLogic::WEAPON_USE_UTILLITY_PRESS);
}
- void GameSession::Gameplay_PlayerJump ( Protocol_PlayerJump& p, DanBias::GameClient* c )
- {
- if(p.hasJumped) c->GetPlayer()->Move(GameLogic::PLAYER_MOVEMENT_JUMP);
- }
- void GameSession::Gameplay_ObjectPickup ( Protocol_ObjectPickup& p, DanBias::GameClient* c )
+
+
+ void GameSession::Gameplay_ObjectPickup ( Protocol_ObjectPickup& p, DanBias::GameClient* c )
{
}
- void GameSession::Gameplay_ObjectDamage ( Protocol_ObjectDamage& p, DanBias::GameClient* c )
+ void GameSession::Gameplay_ObjectDamage ( Protocol_ObjectDamage& p, DanBias::GameClient* c )
{
}
- void GameSession::Gameplay_ObjectPosition ( Protocol_ObjectPosition& p, DanBias::GameClient* c )
+ void GameSession::Gameplay_ObjectPosition ( Protocol_ObjectPosition& p, DanBias::GameClient* c )
{
}
- void GameSession::Gameplay_ObjectEnabled ( Protocol_ObjectEnable& p, DanBias::GameClient* c )
+ void GameSession::Gameplay_ObjectEnabled ( Protocol_ObjectEnable& p, DanBias::GameClient* c )
{
}
- void GameSession::Gameplay_ObjectDisabled ( Protocol_ObjectDisable& p, DanBias::GameClient* c )
+ void GameSession::Gameplay_ObjectDisabled ( Protocol_ObjectDisable& p, DanBias::GameClient* c )
{
}
- void GameSession::Gameplay_ObjectCreate ( Protocol_ObjectCreate& p, DanBias::GameClient* c )
+ void GameSession::Gameplay_ObjectCreate ( Protocol_ObjectCreate& p, DanBias::GameClient* c )
{
}
- void GameSession::General_Status ( Protocol_General_Status& p, DanBias::GameClient* c )
+ void GameSession::General_Status ( Protocol_General_Status& p, DanBias::GameClient* c )
{
switch (p.status)
{
@@ -276,7 +244,7 @@ namespace DanBias
break;
}
}
- void GameSession::General_Text ( Protocol_General_Text& p, DanBias::GameClient* c )
+ void GameSession::General_Text ( Protocol_General_Text& p, DanBias::GameClient* c )
{
printf("Message recieved from (%i):\t %s\n", c->GetClient()->GetID(), p.text.c_str());
}
diff --git a/Code/Game/GameServer/Implementation/GameSession_General.cpp b/Code/Game/GameServer/Implementation/GameSession_General.cpp
index 97cb1f7e..bfa573ee 100644
--- a/Code/Game/GameServer/Implementation/GameSession_General.cpp
+++ b/Code/Game/GameServer/Implementation/GameSession_General.cpp
@@ -137,9 +137,12 @@ namespace DanBias
{
if(this->clients[i])
{
- readyList.Push(this->clients[i]);
- Protocol_LobbyCreateGame p(readyList[i]->GetPlayer()->GetID(), "char_white.dan", readyList[i]->GetPlayer()->GetOrientation());
- readyList[readyList.Size() - 1]->GetClient()->Send(p);
+ if(this->clients[i]->IsReady())
+ {
+ readyList.Push(this->clients[i]);
+ Protocol_LobbyCreateGame p(readyList[i]->GetPlayer()->GetID(), "char_white.dan", readyList[i]->GetPlayer()->GetOrientation());
+ readyList[readyList.Size() - 1]->GetClient()->Send(p);
+ }
}
}
@@ -158,6 +161,7 @@ namespace DanBias
{
if((this->clients[k] && readyList[i]) && readyList[i]->GetClient()->GetID() != this->clients[k]->GetClient()->GetID())
{
+ //Protocol_ObjectCreatePlayer
Protocol_ObjectCreate p(this->clients[k]->GetPlayer()->GetOrientation(), this->clients[k]->GetPlayer()->GetID(), "char_white.dan"); //The model name will be custom later..
readyList[i]->GetClient()->Send(p);
}
@@ -227,6 +231,5 @@ namespace DanBias
this->clients.Clear();
}
-
}//End namespace DanBias
diff --git a/Code/GamePhysics/GamePhysics.vcxproj b/Code/GamePhysics/GamePhysics.vcxproj
index 1abcc6f8..dd2f8fd5 100644
--- a/Code/GamePhysics/GamePhysics.vcxproj
+++ b/Code/GamePhysics/GamePhysics.vcxproj
@@ -89,7 +89,7 @@
Level3
Disabled
- $(SolutionDir)Misc;$(SolutionDir)OysterMath;$(SolutionDir)OysterPhysics3D;%(AdditionalIncludeDirectories)
+ $(SolutionDir)Misc;$(SolutionDir)OysterMath;$(SolutionDir)OysterPhysics3D;$(SolutionDir)Physics\Bullet Source\
_WINDLL;PHYSICS_DLL_EXPORT;%(PreprocessorDefinitions)
false
@@ -97,13 +97,14 @@
true
+ $(SolutionDir)Physics/lib/debug/BulletCollision_Debug.lib;$(SolutionDir)Physics/lib/debug/BulletDynamics_Debug.lib;$(SolutionDir)Physics/lib/debug/LinearMath_Debug.lib;%(AdditionalDependencies)
Level3
Disabled
- $(SolutionDir)Misc;$(SolutionDir)OysterMath;$(SolutionDir)OysterPhysics3D;%(AdditionalIncludeDirectories)
+ $(SolutionDir)Misc;$(SolutionDir)OysterMath;$(SolutionDir)OysterPhysics3D;$(SolutionDir)Physics\Bullet Source\
_WINDLL;PHYSICS_DLL_EXPORT;%(PreprocessorDefinitions)
false
@@ -119,7 +120,7 @@
MaxSpeed
true
true
- $(SolutionDir)Misc;$(SolutionDir)OysterMath;$(SolutionDir)OysterPhysics3D;%(AdditionalIncludeDirectories)
+ $(SolutionDir)Misc;$(SolutionDir)OysterMath;$(SolutionDir)OysterPhysics3D;$(SolutionDir)Physics\Bullet Source\
_WINDLL;PHYSICS_DLL_EXPORT;%(PreprocessorDefinitions)
false
@@ -137,7 +138,7 @@
MaxSpeed
true
true
- $(SolutionDir)Misc;$(SolutionDir)OysterMath;$(SolutionDir)OysterPhysics3D;%(AdditionalIncludeDirectories)
+ $(SolutionDir)Misc;$(SolutionDir)OysterMath;$(SolutionDir)OysterPhysics3D;$(SolutionDir)Physics\Bullet Source\
_WINDLL;PHYSICS_DLL_EXPORT;%(PreprocessorDefinitions)
false
diff --git a/Code/GamePhysics/Implementation/Octree.cpp b/Code/GamePhysics/Implementation/Octree.cpp
index 47bf3e39..4778e5f1 100644
--- a/Code/GamePhysics/Implementation/Octree.cpp
+++ b/Code/GamePhysics/Implementation/Octree.cpp
@@ -31,11 +31,11 @@ Octree& Octree::operator=(const Octree& orig)
void Octree::AddObject(UniquePointer< ICustomBody > customBodyRef)
{
- customBodyRef->SetScene( this );
+ //customBodyRef->SetScene( this );
Data data;
//Data* tempPtr = this->worldNode.dataPtr;
- data.container = customBodyRef->GetBoundingSphere();
+ //data.container = customBodyRef->GetBoundingSphere();
data.queueRef = -1;
data.next = NULL;
data.prev = NULL;
@@ -140,6 +140,7 @@ void Octree::Visit(ICustomBody* customBodyRef, VisitorAction hitAction )
{
auto object = this->mapReferences.find(customBodyRef);
+ // If rigid body is not found
if(object == this->mapReferences.end())
{
return;
@@ -147,8 +148,10 @@ void Octree::Visit(ICustomBody* customBodyRef, VisitorAction hitAction )
unsigned int tempRef = object->second;
+ // Go through all object and test for intersection
for(unsigned int i = 0; ileafData.size(); i++)
{
+ // If objects intersect call collision response function
if(tempRef != i && !this->leafData[i].limbo) if(this->leafData[tempRef].container.Intersects(this->leafData[i].container))
{
hitAction(*this, tempRef, i);
@@ -213,7 +216,7 @@ unsigned int Octree::GetTemporaryReferenceOf( const ICustomBody* objRef ) const
void Octree::SetAsAltered( unsigned int tempRef )
{
- this->leafData[tempRef].container = this->leafData[tempRef].customBodyRef->GetBoundingSphere();
+ //this->leafData[tempRef].container = this->leafData[tempRef].customBodyRef->GetBoundingSphere();
//! @todo TODO: implement stub
}
diff --git a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp
index 7981322f..9026a60f 100644
--- a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp
+++ b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.cpp
@@ -12,149 +12,6 @@ using namespace ::Utility::Value;
API_Impl API_instance;
-namespace
-{
- void OnPossibleCollision( Octree& worldScene, unsigned int protoTempRef, unsigned int deuterTempRef )
- {
- auto proto = worldScene.GetCustomBody( protoTempRef );
- auto deuter = worldScene.GetCustomBody( deuterTempRef );
-
- Float4 worldPointOfContact;
- if( proto->Intersects(*deuter, worldPointOfContact) )
- {
- // Apply CollisionResponse in pure gather pattern
- ICustomBody::State protoState; proto->GetState( protoState );
- ICustomBody::State deuterState; deuter->GetState( deuterState );
-
- // calc from perspective of deuter.
- Float4 normal = (worldPointOfContact - Float4(deuterState.GetCenterPosition(), 1.0f )).GetNormalized(); // Init value is only borrowed
- if( normal.Dot(normal) > 0.0f )
- {
- deuter->GetNormalAt( worldPointOfContact, normal );
- }
- else
- { // special case: deuter is completly contained within proto or they have overlapping centers.
-
- normal = Float4( protoState.GetCenterPosition() - deuterState.GetCenterPosition(), 0.0f );
- if( normal.Dot(normal) == 0.0f )
- { // they have overlapping centers. Rebound at least
- // calculate and store time interpolation value, for later rebound.
- proto->SetTimeOfContact( worldPointOfContact );
- return;
- }
-
- // borrowing the negated normal of proto.
- proto->GetNormalAt( worldPointOfContact, normal );
- normal = -normal;
- }
- normal.Normalize();
-
- Float4 protoG = Float4(protoState.GetLinearMomentum( worldPointOfContact.xyz ), 0),
- deuterG = Float4(deuterState.GetLinearMomentum( worldPointOfContact.xyz ), 0);
-
- if( normal != normal ) // debug: trap
- const char *breakpoint = "This should never happen";
-
- if( protoG != protoG ) // debug: trap
- const char *breakpoint = "This should never happen";
-
- if( deuterG != deuterG ) // debug: trap
- const char *breakpoint = "This should never happen";
-
- Float protoG_Magnitude = protoG.Dot( normal ),
- deuterG_Magnitude = deuterG.Dot( normal );
-
- // if they are not relatively moving towards eachother, there is no collision
- Float deltaPos = normal.Dot( Float4(deuterState.GetCenterPosition(), 1) - Float4(protoState.GetCenterPosition(), 1) );
- if( deltaPos < 0.0f )
- {
- if( protoG_Magnitude >= deuterG_Magnitude )
- {
- return;
- }
- }
- else if( deltaPos > 0.0f )
- {
- if( protoG_Magnitude <= deuterG_Magnitude )
- {
- return;
- }
- }
- else
- {
- return;
- }
-
- if( proto->CallSubscription_BeforeCollisionResponse(proto) == ICustomBody::SubscriptMessage_ignore_collision_response )
- {
- return;
- }
-
- // PLayerHAck
- if( proto->CallSubscription_BeforeCollisionResponse(proto) == ICustomBody::SubscriptMessage_player_collision_response )
- {
- Float3 linearMomentum = protoState.GetLinearMomentum();
- Float3 up = -protoState.GetGravityNormal();
- Float3 upForce = (linearMomentum.Dot(up) * up);
-
- Float3 noBounceForce = linearMomentum - upForce;
- protoState.SetLinearMomentum(noBounceForce);
- proto->SetState(protoState);
- return;
- }
- // calculate and store time interpolation value, for later rebound.
- proto->SetTimeOfContact( worldPointOfContact );
-
- // bounce
- Float4 bounceD = normal * -Formula::CollisionResponse::Bounce( deuterState.GetRestitutionCoeff(),
- deuterState.GetMass(), deuterG_Magnitude,
- protoState.GetMass(), protoG_Magnitude );
-
-
- // calc from perspective of proto
-
- normal = (worldPointOfContact - Float4(protoState.GetCenterPosition(), 1.0f )).GetNormalized();
- if( normal.Dot(normal) > 0.0f )
- {
- proto->GetNormalAt( worldPointOfContact, normal );
- protoG_Magnitude = protoG.Dot( normal );
- deuterG_Magnitude = deuterG.Dot( normal );
- }
- else
- { // special case: proto is completly contained within deuter.
- // borrowing the negated normal of deuter.
- deuter->GetNormalAt( worldPointOfContact, normal );
- normal = -normal;
- protoG_Magnitude = -protoG_Magnitude;
- deuterG_Magnitude = -deuterG_Magnitude;
- }
-
- if( normal != normal ) // debug: trap
- const char *breakpoint = "This should never happen";
-
- // bounce
- Float4 bounceP = normal * Formula::CollisionResponse::Bounce( protoState.GetRestitutionCoeff(),
- protoState.GetMass(), protoG_Magnitude,
- deuterState.GetMass(), deuterG_Magnitude );
-
- Float4 bounce = Average( bounceD, bounceP );
-
- Float4 friction = Formula::CollisionResponse::Friction( protoG_Magnitude, normal,
- Float4(protoState.GetLinearMomentum(), 0), protoState.GetFrictionCoeff_Static(), protoState.GetFrictionCoeff_Kinetic(), protoState.GetMass(),
- Float4(deuterState.GetLinearMomentum(), 0), deuterState.GetFrictionCoeff_Static(), deuterState.GetFrictionCoeff_Kinetic(), deuterState.GetMass());
-
- Float kineticEnergyPBefore = Oyster::Physics3D::Formula::LinearKineticEnergy( protoState.GetMass(), protoState.GetLinearMomentum()/protoState.GetMass() );
-
- protoState.ApplyImpulse( bounce.xyz - friction.xyz, worldPointOfContact.xyz, normal.xyz );
- proto->SetState( protoState );
-
- Float kineticEnergyPAFter = Oyster::Physics3D::Formula::LinearKineticEnergy( protoState.GetMass(), (protoState.GetLinearMomentum() + protoState.GetLinearImpulse())/protoState.GetMass() );
-
- proto->CallSubscription_AfterCollisionResponse( deuter, kineticEnergyPBefore - kineticEnergyPAFter );
- }
- }
-}
-
API & API::Instance()
{
return API_instance;
@@ -162,312 +19,250 @@ API & API::Instance()
API_Impl::API_Impl()
{
- this->gravityConstant = Constant::gravity_constant;
- this->epsilon = Constant::epsilon;
- this->updateFrameLength = 1.0f / 120.0f;
- this->destructionAction = Default::EventAction_Destruction;
- this->gravity = ::std::vector();
- this->worldScene = Octree();
+ this->broadphase = NULL;
+ this->collisionConfiguration = NULL;
+ this->dispatcher = NULL;
+ this->solver = NULL;
+ this->dynamicsWorld = NULL;
}
-API_Impl::~API_Impl() {}
-
-void API_Impl::Init( unsigned int numObjects, unsigned int numGravityWells , const Float3 &worldSize )
+API_Impl::~API_Impl()
{
- unsigned char numLayers = 4; //!< @todo TODO: calc numLayers from worldSize
- this->gravity.resize( 0 );
- this->gravity.reserve( numGravityWells );
- this->worldScene = Octree( numObjects, numLayers, worldSize );
-}
+ delete this->dynamicsWorld;
+ this->dynamicsWorld = NULL;
+ delete this->solver;
+ this->solver = NULL;
+ delete this->dispatcher;
+ this->dispatcher = NULL;
+ delete this->collisionConfiguration;
+ this->collisionConfiguration = NULL;
+ delete this->broadphase;
+ this->broadphase = NULL;
-void API_Impl::SetFrameTimeLength( float deltaTime )
-{
- this->updateFrameLength = deltaTime;
-}
-
-void API_Impl::SetGravityConstant( float g )
-{
- this->gravityConstant = g;
-}
-
-void API_Impl::SetEpsilon( float e )
-{
- this->epsilon = e;
-}
-
-void API_Impl::SetSubscription( API::EventAction_Destruction functionPointer )
-{
- if( functionPointer )
+ for(int i = 0; i < this->customBodies.size(); i++)
{
- this->destructionAction = functionPointer;
- }
- else
- {
- this->destructionAction = Default::EventAction_Destruction;
+ delete this->customBodies[i];
+ this->customBodies[i] = NULL;
}
}
-float API_Impl::GetFrameTimeLength() const
+// Bullet physics
+ICustomBody* API_Impl::AddCollisionSphere(float radius, ::Oyster::Math::Float4 rotation, ::Oyster::Math::Float3 position, float mass, float restitution, float staticFriction, float dynamicFriction)
{
- return this->updateFrameLength;
+ SimpleRigidBody* body = new SimpleRigidBody;
+ SimpleRigidBody::State state;
+
+ // Add collision shape
+ btCollisionShape* collisionShape = new btSphereShape(radius);
+ body->SetCollisionShape(collisionShape);
+
+ // Add motion state
+ btDefaultMotionState* motionState = new btDefaultMotionState(btTransform(btQuaternion(rotation.x, rotation.y, rotation.z, rotation.w),btVector3(position.x, position.y, position.z)));
+ body->SetMotionState(motionState);
+
+ // Add rigid body
+ btVector3 fallInertia(0, 0, 0);
+ collisionShape->calculateLocalInertia(mass, fallInertia);
+ btRigidBody::btRigidBodyConstructionInfo rigidBodyCI(mass, motionState, collisionShape, fallInertia);
+ btRigidBody* rigidBody = new btRigidBody(rigidBodyCI);
+ rigidBody->setFriction(staticFriction);
+ rigidBody->setRestitution(restitution);
+ rigidBody->setUserPointer(body);
+ body->SetRigidBody(rigidBody);
+
+ // Add rigid body to world
+ this->dynamicsWorld->addRigidBody(rigidBody);
+ this->customBodies.push_back(body);
+
+ state.centerPos = position;
+ state.reach = Float3(radius, radius, radius);
+ state.dynamicFrictionCoeff = 0.5f;
+ state.staticFrictionCoeff = 0.5f;
+ state.quaternion = Quaternion(Float3(rotation.xyz), rotation.w);
+ state.mass = mass;
+
+ body->SetState(state);
+
+ return body;
}
-void API_Impl::Update()
-{ /** @todo TODO: Update is a temporary solution .*/
- ::std::vector updateList;
- auto proto = this->worldScene.Sample( Universe(), updateList ).begin();
+ICustomBody* API_Impl::AddCollisionBox(Float3 halfSize, ::Oyster::Math::Float4 rotation, ::Oyster::Math::Float3 position, float mass, float restitution, float staticFriction, float dynamicFriction)
+{
+ SimpleRigidBody* body = new SimpleRigidBody;
+ SimpleRigidBody::State state;
+
+ // Add collision shape
+ btCollisionShape* collisionShape = new btBoxShape(btVector3(halfSize.x, halfSize.y, halfSize.z));
+ body->SetCollisionShape(collisionShape);
+
+ // Add motion state
+ btDefaultMotionState* motionState = new btDefaultMotionState(btTransform(btQuaternion(rotation.x, rotation.y, rotation.z, rotation.w),btVector3(position.x, position.y, position.z)));
+ body->SetMotionState(motionState);
+
+ // Add rigid body
+ btVector3 fallInertia(0, 0, 0);
+ collisionShape->calculateLocalInertia(mass, fallInertia);
+ btRigidBody::btRigidBodyConstructionInfo rigidBodyCI(mass, motionState, collisionShape, fallInertia);
+ btRigidBody* rigidBody = new btRigidBody(rigidBodyCI);
+ rigidBody->setFriction(staticFriction);
+ rigidBody->setRestitution(restitution);
+ rigidBody->setUserPointer(body);
+ body->SetRigidBody(rigidBody);
+
+ // Add rigid body to world
+ this->dynamicsWorld->addRigidBody(rigidBody);
+ this->customBodies.push_back(body);
+
+ state.centerPos = position;
+ state.reach = halfSize;
+ state.dynamicFrictionCoeff = 0.5f;
+ state.staticFrictionCoeff = 0.5f;
+ state.quaternion = Quaternion(Float3(rotation.xyz), rotation.w);
+ state.mass = mass;
+
+ body->SetState(state);
+
+ return body;
+}
+
+ICustomBody* API_Impl::AddCollisionCylinder(::Oyster::Math::Float3 halfSize, ::Oyster::Math::Float4 rotation, ::Oyster::Math::Float3 position, float mass, float restitution, float staticFriction, float dynamicFriction)
+{
+ SimpleRigidBody* body = new SimpleRigidBody;
+ SimpleRigidBody::State state;
+
+ // Add collision shape
+ btCollisionShape* collisionShape = new btCylinderShape(btVector3(halfSize.x, halfSize.y, halfSize.z));
+ body->SetCollisionShape(collisionShape);
+
+ // Add motion state
+ btDefaultMotionState* motionState = new btDefaultMotionState(btTransform(btQuaternion(rotation.x, rotation.y, rotation.z, rotation.w),btVector3(position.x, position.y, position.z)));
+ body->SetMotionState(motionState);
+
+ // Add rigid body
+ btVector3 fallInertia(0, 0, 0);
+ collisionShape->calculateLocalInertia(mass, fallInertia);
+ btRigidBody::btRigidBodyConstructionInfo rigidBodyCI(mass, motionState, collisionShape, fallInertia);
+ btRigidBody* rigidBody = new btRigidBody(rigidBodyCI);
+ rigidBody->setFriction(staticFriction);
+ rigidBody->setRestitution(restitution);
+ rigidBody->setUserPointer(body);
+ body->SetRigidBody(rigidBody);
+
+ // Add rigid body to world
+ this->dynamicsWorld->addRigidBody(rigidBody);
+ this->customBodies.push_back(body);
+
+ state.centerPos = position;
+ state.reach = halfSize;
+ state.dynamicFrictionCoeff = 0.5f;
+ state.staticFrictionCoeff = 0.5f;
+ state.quaternion = Quaternion(Float3(rotation.xyz), rotation.w);
+ state.mass = mass;
+
+ body->SetState(state);
+
+ return body;
+}
+
+void API_Impl::UpdateWorld()
+{
+ this->dynamicsWorld->stepSimulation(1.0f/60.0f, 1.0f, 1.0f/60.0f);
+
ICustomBody::State state;
- for( ; proto != updateList.end(); ++proto )
+
+ for(unsigned int i = 0; i < this->customBodies.size(); i++ )
{
- // Step 1: Apply Gravity
- Float4 gravityImpulse = Float4::null;
- (*proto)->GetState( state );
- for( ::std::vector::size_type i = 0; i < this->gravity.size(); ++i )
+ btTransform trans;
+ dynamic_cast(this->customBodies[i])->GetMotionState()->getWorldTransform(trans);
+ this->customBodies[i]->SetPosition(Float3(trans.getOrigin().x(), trans.getOrigin().y(), trans.getOrigin().z()));
+ this->customBodies[i]->SetRotation(Quaternion(Float3(trans.getRotation().x(), trans.getRotation().y(), trans.getRotation().z()), trans.getRotation().w()));
+
+ if(dynamic_cast(this->customBodies[i])->GetRigidBody()->getActivationState() == ACTIVE_TAG)
{
- switch( this->gravity[i].gravityType )
- {
- case Gravity::GravityType_Well:
- {
- Float4 d = Float4( this->gravity[i].well.position, 1.0f ) - Float4( state.GetCenterPosition(), 1.0f );
- Float rSquared = d.Dot( d );
- if( rSquared != 0.0 )
- {
- Float force = Physics3D::Formula::ForceField( this->gravityConstant, state.GetMass(), this->gravity[i].well.mass, rSquared );
- gravityImpulse += (this->updateFrameLength * force / ::std::sqrt(rSquared)) * d;
- }
- break;
- }
- case Gravity::GravityType_Directed:
- gravityImpulse += Float4( this->gravity[i].directed.impulse, 0.0f );
- break;
-// case Gravity::GravityType_DirectedField:
-// //this->gravity[i].directedField.
-// //! TODO: @todo rethink
-// break;
- default: break;
+ dynamic_cast(this->customBodies[i])->CallSubscription_Move();
+ }
+ }
+
+ int numManifolds = this->dynamicsWorld->getDispatcher()->getNumManifolds();
+ for (int i=0;idynamicsWorld->getDispatcher()->getManifoldByIndexInternal(i);
+ const btCollisionObject* obA = contactManifold->getBody0();
+ const btCollisionObject* obB = contactManifold->getBody1();
+
+ ICustomBody* bodyA = (ICustomBody*)obA->getUserPointer();
+ ICustomBody* bodyB = (ICustomBody*)obB->getUserPointer();
+
+ dynamic_cast(bodyA)->CallSubscription_AfterCollisionResponse(bodyA, bodyB, 0.0f);
+ dynamic_cast(bodyB)->CallSubscription_AfterCollisionResponse(bodyB, bodyA, 0.0f);
+
+ int numContacts = contactManifold->getNumContacts();
+ for (int j=0;jgetContactPoint(j);
+ if (pt.getDistance()<0.f)
+ {
+ const btVector3& ptA = pt.getPositionWorldOnA();
+ const btVector3& ptB = pt.getPositionWorldOnB();
+ const btVector3& normalOnB = pt.m_normalWorldOnB;
}
}
-
- if( gravityImpulse != gravityImpulse ) // debug: trap
- const char *breakpoint = "This should never happen";
-
- if( gravityImpulse != Float4::null )
- {
- state.ApplyLinearImpulse( gravityImpulse.xyz );
- state.SetGravityNormal( gravityImpulse.GetNormalized().xyz );
- (*proto)->SetState( state );
- }
-
- // Step 2: Apply Collision Response
- this->worldScene.Visit( *proto, OnPossibleCollision );
}
- proto = updateList.begin();
- for( ; proto != updateList.end(); ++proto )
- {
- (*proto)->GetState( state );
- Float3 lM = state.GetLinearMomentum();
-
- //LinearAlgebra3D::InterpolateAxisYToNormal_UsingNlerp(state.SetOrientation(, Float4(state.GetGravityNormal(), 0.0f), 1.0f);
-
-
- if( abs(lM.x) < this->epsilon )
- {
- state.linearMomentum.x = 0;
- }
- if( abs(lM.y) < this->epsilon )
- {
- state.linearMomentum.y = 0;
- }
- if( abs(lM.z) < this->epsilon )
- {
- state.linearMomentum.z = 0;
- }
-
- (*proto)->SetState( state );
-
- switch( (*proto)->Update(this->updateFrameLength) )
- {
- case UpdateState_altered:
- this->worldScene.SetAsAltered( this->worldScene.GetTemporaryReferenceOf(*proto) );
- (*proto)->CallSubscription_Move();
- case UpdateState_resting:
- default:
- break;
- }
- }
}
+void API_Impl::Init()
+{
+ this->broadphase = new btDbvtBroadphase();
+ this->collisionConfiguration = new btDefaultCollisionConfiguration();
+ this->dispatcher = new btCollisionDispatcher(this->collisionConfiguration);
+ this->solver = new btSequentialImpulseConstraintSolver;
+ this->dynamicsWorld = new btDiscreteDynamicsWorld(this->dispatcher,this->broadphase,this->solver,this->collisionConfiguration);
+ this->dynamicsWorld->setGravity(btVector3(0,-10,0));
+}
+
+
bool API_Impl::IsInLimbo( const ICustomBody* objRef )
{
- return this->worldScene.IsInLimbo( objRef );
+ return true;
}
void API_Impl::MoveToLimbo( const ICustomBody* objRef )
{
- this->worldScene.MoveToLimbo( objRef );
+
}
+
void API_Impl::ReleaseFromLimbo( const ICustomBody* objRef )
{
- this->worldScene.ReleaseFromLimbo( objRef );
-}
-
-void API_Impl::AddObject( ::Utility::DynamicMemory::UniquePointer handle )
-{
- this->worldScene.AddObject( handle );
-}
-
-UniquePointer API_Impl::ExtractObject( const ICustomBody* objRef )
-{
- return this->worldScene.Extract( objRef );
-}
-
-void API_Impl::DestroyObject( const ICustomBody* objRef )
-{
- UniquePointer object = this->worldScene.Extract( objRef );
- if( object )
- {
- this->destructionAction( object );
- }
-}
-
-void API_Impl::AddGravity( const API::Gravity &g )
-{
- this->gravity.push_back( g );
-}
-
-void API_Impl::RemoveGravity( const API::Gravity &g )
-{
- for( ::std::vector::size_type i = this->gravity.size() - 1; i >= 0; --i )
- {
- if( g == this->gravity[i] )
- {
- int end = this->gravity.size() - 1;
- this->gravity[i] = this->gravity[end];
- this->gravity.resize( end );
- }
- }
+
}
void API_Impl::ApplyEffect( const Oyster::Collision3D::ICollideable& collideable, void* args, void(hitAction)(ICustomBody*, void*) )
{
- this->worldScene.Visit(collideable, args, hitAction);
+
}
-//void API_Impl::ApplyForceAt( const ICustomBody* objRef, const Float3 &worldPos, const Float3 &worldF )
-//{
-// unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef );
-// if( tempRef != this->worldScene.invalid_ref )
-// {
-// //this->worldScene.GetCustomBody( tempRef )->Apply //!< @todo TODO: need function
-// this->worldScene.SetAsAltered( tempRef );
-// }
-//}
-//
-//void API_Impl::SetMomentOfInertiaTensor_KeepVelocity( const ICustomBody* objRef, const Float4x4 &localI )
-//{ // deprecated
-// unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef );
-// if( tempRef != this->worldScene.invalid_ref )
-// {
-// this->worldScene.GetCustomBody( tempRef )->SetMomentOfInertiaTensor_KeepVelocity( localI );
-// }
-//}
-//
-//void API_Impl::SetMomentOfInertiaTensor_KeepMomentum( const ICustomBody* objRef, const Float4x4 &localI )
-//{ // deprecated
-// unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef );
-// if( tempRef != this->worldScene.invalid_ref )
-// {
-// this->worldScene.GetCustomBody( tempRef )->SetMomentOfInertiaTensor_KeepMomentum( localI );
-// }
-//}
-//
-//void API_Impl::SetMass_KeepVelocity( const ICustomBody* objRef, Float m )
-//{ // deprecated
-// unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef );
-// if( tempRef != this->worldScene.invalid_ref )
-// {
-// this->worldScene.GetCustomBody( tempRef )->SetMass_KeepVelocity( m );
-// }
-//}
-//
-//void API_Impl::SetMass_KeepMomentum( const ICustomBody* objRef, Float m )
-//{ // deprecated
-// unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef );
-// if( tempRef != this->worldScene.invalid_ref )
-// {
-// this->worldScene.GetCustomBody( tempRef )->SetMass_KeepMomentum( m );
-// }
-//}
-//
-//void API_Impl::SetCenter( const ICustomBody* objRef, const Float3 &worldPos )
-//{
-// unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef );
-// if( tempRef != this->worldScene.invalid_ref )
-// {
-// //this->worldScene.GetCustomBody( tempRef )->Set //!< @todo TODO: need function
-// this->worldScene.EvaluatePosition( tempRef );
-// }
-//}
-//
-//void API_Impl::SetRotation( const ICustomBody* objRef, const Float4x4 &rotation )
-//{
-// unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef );
-// if( tempRef != this->worldScene.invalid_ref )
-// {
-// this->worldScene.GetCustomBody( tempRef )->SetRotation( rotation );
-// this->worldScene.EvaluatePosition( tempRef );
-// }
-//}
-//
-//void API_Impl::SetOrientation( const ICustomBody* objRef, const Float4x4 &orientation )
-//{
-// unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef );
-// if( tempRef != this->worldScene.invalid_ref )
-// {
-// this->worldScene.GetCustomBody( tempRef )->SetOrientation( orientation );
-// this->worldScene.EvaluatePosition( tempRef );
-// }
-//}
-//
-//void API_Impl::SetSize( const ICustomBody* objRef, const Float3 &size )
-//{
-// unsigned int tempRef = this->worldScene.GetTemporaryReferenceOf( objRef );
-// if( tempRef != this->worldScene.invalid_ref )
-// {
-// this->worldScene.GetCustomBody( tempRef )->SetSize( size );
-// this->worldScene.EvaluatePosition( tempRef );
-// }
-//}
-
-UniquePointer API_Impl::CreateRigidBody( const API::SimpleBodyDescription &desc ) const
-{
- return new SimpleRigidBody( desc );
-}
-
-UniquePointer API_Impl::CreateRigidBody( const API::SphericalBodyDescription &desc ) const
-{
- return new SphericalRigidBody( desc );
-}
-
-namespace Oyster { namespace Physics
-{
- namespace Default
+namespace Oyster
+{
+ namespace Physics
{
- void EventAction_Destruction( ::Utility::DynamicMemory::UniquePointer<::Oyster::Physics::ICustomBody> proto )
- { /* Do nothing except allowing the proto uniquePointer destroy itself. */ }
+ namespace Default
+ {
+ void EventAction_Destruction( ::Utility::DynamicMemory::UniquePointer<::Oyster::Physics::ICustomBody> proto )
+ { /* Do nothing except allowing the proto uniquePointer destroy itself. */ }
- ::Oyster::Physics::ICustomBody::SubscriptMessage EventAction_BeforeCollisionResponse( const ::Oyster::Physics::ICustomBody *proto, const ::Oyster::Physics::ICustomBody *deuter )
- { /* Do nothing except returning business as usual. */
- return ::Oyster::Physics::ICustomBody::SubscriptMessage_none;
+ ::Oyster::Physics::ICustomBody::SubscriptMessage EventAction_BeforeCollisionResponse( const ::Oyster::Physics::ICustomBody *proto, const ::Oyster::Physics::ICustomBody *deuter )
+ { /* Do nothing except returning business as usual. */
+ return ::Oyster::Physics::ICustomBody::SubscriptMessage_none;
+ }
+
+ void EventAction_AfterCollisionResponse( const ::Oyster::Physics::ICustomBody *proto, const ::Oyster::Physics::ICustomBody *deuter, ::Oyster::Math::Float kineticEnergyLoss )
+ { /* Do nothing except returning business as usual. */
+
+ }
+
+ void EventAction_Move( const ::Oyster::Physics::ICustomBody *object )
+ { /* Do nothing. */ }
}
-
- void EventAction_AfterCollisionResponse( const ::Oyster::Physics::ICustomBody *proto, const ::Oyster::Physics::ICustomBody *deuter, ::Oyster::Math::Float kineticEnergyLoss )
- { /* Do nothing except returning business as usual. */
-
- }
-
- void EventAction_Move( const ::Oyster::Physics::ICustomBody *object )
- { /* Do nothing. */ }
- }
-} }
\ No newline at end of file
+ }
+}
\ No newline at end of file
diff --git a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.h b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.h
index 21460944..28111d26 100644
--- a/Code/GamePhysics/Implementation/PhysicsAPI_Impl.h
+++ b/Code/GamePhysics/Implementation/PhysicsAPI_Impl.h
@@ -3,6 +3,7 @@
#include "../PhysicsAPI.h"
#include "Octree.h"
+#include
namespace Oyster
{
@@ -14,49 +15,28 @@ namespace Oyster
API_Impl();
virtual ~API_Impl();
- void Init( unsigned int numObjects, unsigned int numGravityWells , const ::Oyster::Math::Float3 &worldSize );
-
- void SetFrameTimeLength( float deltaTime );
- void SetGravityConstant( float g );
- void SetEpsilon( float e );
- void SetSubscription( EventAction_Destruction functionPointer );
-
- float GetFrameTimeLength() const;
-
- void Update();
+ void Init();
bool IsInLimbo( const ICustomBody* objRef );
void MoveToLimbo( const ICustomBody* objRef );
void ReleaseFromLimbo( const ICustomBody* objRef );
- void AddObject( ::Utility::DynamicMemory::UniquePointer handle );
- ::Utility::DynamicMemory::UniquePointer ExtractObject( const ICustomBody* objRef );
- void DestroyObject( const ICustomBody* objRef );
+ // Bullet physics
+ ICustomBody* AddCollisionSphere(float radius, ::Oyster::Math::Float4 rotation, ::Oyster::Math::Float3 position, float mass, float restitution, float staticFriction, float dynamicFriction);
+ ICustomBody* AddCollisionBox(::Oyster::Math::Float3 halfSize, ::Oyster::Math::Float4 rotation, ::Oyster::Math::Float3 position, float mass, float restitution, float staticFriction, float dynamicFriction);
+ ICustomBody* AddCollisionCylinder(::Oyster::Math::Float3 halfSize, ::Oyster::Math::Float4 rotation, ::Oyster::Math::Float3 position, float mass, float restitution, float staticFriction, float dynamicFriction);
- void AddGravity( const API::Gravity &g );
- void RemoveGravity( const API::Gravity &g );
+ void UpdateWorld();
void ApplyEffect( const Oyster::Collision3D::ICollideable& collideable, void* args, void(hitAction)(ICustomBody*, void*) );
- //void ApplyForceAt( const ICustomBody* objRef, const ::Oyster::Math::Float3 &worldPos, const ::Oyster::Math::Float3 &worldF );
-
- //void SetMomentOfInertiaTensor_KeepVelocity( const ICustomBody* objRef, const ::Oyster::Math::Float4x4 &localI );
- //void SetMomentOfInertiaTensor_KeepMomentum( const ICustomBody* objRef, const ::Oyster::Math::Float4x4 &localI );
- //void SetMass_KeepVelocity( const ICustomBody* objRef, ::Oyster::Math::Float m );
- //void SetMass_KeepMomentum( const ICustomBody* objRef, ::Oyster::Math::Float m );
- //void SetCenter( const ICustomBody* objRef, const ::Oyster::Math::Float3 &worldPos );
- //void SetRotation( const ICustomBody* objRef, const ::Oyster::Math::Float4x4 &rotation );
- //void SetOrientation( const ICustomBody* objRef, const ::Oyster::Math::Float4x4 &orientation );
- //void SetSize( const ICustomBody* objRef, const ::Oyster::Math::Float3 &size );
-
- ::Utility::DynamicMemory::UniquePointer CreateRigidBody( const SimpleBodyDescription &desc ) const;
- ::Utility::DynamicMemory::UniquePointer CreateRigidBody( const SphericalBodyDescription &desc ) const;
-
private:
- ::Oyster::Math::Float gravityConstant, updateFrameLength, epsilon;
- EventAction_Destruction destructionAction;
- ::std::vector gravity;
- Octree worldScene;
+ btBroadphaseInterface* broadphase;
+ btDefaultCollisionConfiguration* collisionConfiguration;
+ btCollisionDispatcher* dispatcher;
+ btSequentialImpulseConstraintSolver* solver;
+ btDiscreteDynamicsWorld* dynamicsWorld;
+ std::vector customBodies;
};
namespace Default
diff --git a/Code/GamePhysics/Implementation/SimpleRigidBody.cpp b/Code/GamePhysics/Implementation/SimpleRigidBody.cpp
index b57c2a97..879ff8bc 100644
--- a/Code/GamePhysics/Implementation/SimpleRigidBody.cpp
+++ b/Code/GamePhysics/Implementation/SimpleRigidBody.cpp
@@ -8,291 +8,177 @@ using namespace ::Oyster::Collision3D;
using namespace ::Utility::DynamicMemory;
using namespace ::Utility::Value;
-namespace Private
-{
- const Float epsilon = (const Float)1e-20;
-
- // Float calculations can suffer roundingerrors. Which is where epsilon = 1e-20 comes into the picture
- inline bool EqualsZero( const Float &value )
- { // by Dan Andersson
- return Abs( value ) < epsilon;
- }
-
- inline bool Contains( const Plane &container, const Float4 &pos )
- { // by Dan Andersson
- return EqualsZero( container.normal.Dot( pos ) + container.phasing );
- }
-
- // revision of Ray Vs Plane intersect test, there ray is more of an axis
- bool Intersects( const Ray &axis, const Plane &plane, Float &connectDistance )
- { // by Dan Andersson
- Float c = plane.normal.Dot(axis.direction);
- if( EqualsZero(c) )
- { // axis is parallell with the plane. (axis direction orthogonal with the planar normal)
- connectDistance = 0.0f;
- return Contains( plane, axis.origin );
- }
-
- connectDistance = -plane.phasing;
- connectDistance -= plane.normal.Dot( axis.origin );
- connectDistance /= c;
-
- return true;
- }
-}
-
SimpleRigidBody::SimpleRigidBody()
{
- this->rigid = RigidBody();
- this->rigid.SetMass_KeepMomentum( 16.0f );
- this->gravityNormal = Float3::null;
- this->onCollision = Default::EventAction_BeforeCollisionResponse;
- this->onCollisionResponse = Default::EventAction_AfterCollisionResponse;
- this->onMovement = Default::EventAction_Move;
-
- this->collisionRebound.previousSpatial.center = this->rigid.centerPos;
- this->collisionRebound.previousSpatial.axis = this->rigid.axis;
- this->collisionRebound.previousSpatial.reach = this->rigid.boundingReach;
- this->collisionRebound.timeOfContact = 1.0f;
+ this->collisionShape = NULL;
+ this->motionState = NULL;
+ this->rigidBody = NULL;
+
+ this->state.centerPos = Float3(0.0f, 0.0f, 0.0f);
+ this->state.quaternion = Quaternion(Float3(0.0f, 0.0f, 0.0f), 1.0f);
+ this->state.dynamicFrictionCoeff = 0.0f;
+ this->state.staticFrictionCoeff = 0.0f;
+ this->state.mass = 0.0f;
+ this->state.restitutionCoeff = 0.0f;
+ this->state.reach = Float3(0.0f, 0.0f, 0.0f);
+
+ this->afterCollision = NULL;
+ this->onMovement = NULL;
- this->scene = nullptr;
this->customTag = nullptr;
- this->ignoreGravity = this->isForwarded = false;
}
-SimpleRigidBody::SimpleRigidBody( const API::SimpleBodyDescription &desc )
-{
- this->rigid = RigidBody();
- this->rigid.SetRotation( desc.rotation );
- this->rigid.centerPos = desc.centerPosition;
- this->rigid.SetSize( desc.size );
- this->rigid.restitutionCoeff = desc.restitutionCoeff;
- this->rigid.frictionCoeff_Static = desc.frictionCoeff_Static;
- this->rigid.frictionCoeff_Kinetic = desc.frictionCoeff_Dynamic;
- this->rigid.SetMass_KeepMomentum( desc.mass );
- this->rigid.SetMomentOfInertia_KeepMomentum( desc.inertiaTensor );
- this->deltaPos = Float4::null;
- this->deltaAxis = Float4::null;
-
- this->gravityNormal = Float3::null;
-
- this->collisionRebound.previousSpatial.center = this->rigid.centerPos;
- this->collisionRebound.previousSpatial.axis = this->rigid.axis;
- this->collisionRebound.previousSpatial.reach = this->rigid.boundingReach;
- this->collisionRebound.timeOfContact = 1.0f;
-
- if( desc.subscription_onCollision )
- {
- this->onCollision = desc.subscription_onCollision;
- }
- else
- {
- this->onCollision = Default::EventAction_BeforeCollisionResponse;
- }
-
- if( desc.subscription_onCollisionResponse )
- {
- this->onCollisionResponse = desc.subscription_onCollisionResponse;
- }
- else
- {
- this->onCollisionResponse = Default::EventAction_AfterCollisionResponse;
- }
-
- if( desc.subscription_onMovement )
- {
- this->onMovement= desc.subscription_onMovement;
- }
- else
- {
- this->onMovement = Default::EventAction_Move;
- }
-
- this->scene = nullptr;
- this->customTag = nullptr;
- this->ignoreGravity = desc.ignoreGravity;
-}
-
-SimpleRigidBody::~SimpleRigidBody() {}
-
-UniquePointer SimpleRigidBody::Clone() const
+SimpleRigidBody::~SimpleRigidBody()
{
- return new SimpleRigidBody( *this );
+ delete this->motionState;
+ this->motionState = NULL;
+ delete this->collisionShape;
+ this->collisionShape = NULL;
+ delete this->rigidBody;
+ this->rigidBody = NULL;
}
SimpleRigidBody::State SimpleRigidBody::GetState() const
{
- return State( this->rigid.GetMass(), this->rigid.restitutionCoeff,
- this->rigid.frictionCoeff_Static, this->rigid.frictionCoeff_Kinetic,
- this->rigid.GetMomentOfInertia(), this->rigid.boundingReach,
- this->rigid.centerPos, this->rigid.axis,
- this->rigid.momentum_Linear, this->rigid.momentum_Angular,
- this->rigid.gravityNormal );
+ return this->state;
}
-SimpleRigidBody::State & SimpleRigidBody::GetState( SimpleRigidBody::State &targetMem ) const
+SimpleRigidBody::State& SimpleRigidBody::GetState( SimpleRigidBody::State &targetMem ) const
{
- return targetMem = State( this->rigid.GetMass(), this->rigid.restitutionCoeff,
- this->rigid.frictionCoeff_Static, this->rigid.frictionCoeff_Kinetic,
- this->rigid.GetMomentOfInertia(), this->rigid.boundingReach,
- this->rigid.centerPos, this->rigid.axis,
- this->rigid.momentum_Linear, this->rigid.momentum_Angular,
- this->rigid.gravityNormal );
+ targetMem = this->state;
+ return targetMem;
}
void SimpleRigidBody::SetState( const SimpleRigidBody::State &state )
{
- this->rigid.centerPos = state.GetCenterPosition();
- this->rigid.axis = state.GetAngularAxis();
- this->rigid.boundingReach = state.GetReach();
- this->rigid.momentum_Linear = state.GetLinearMomentum();
- this->rigid.momentum_Angular = state.GetAngularMomentum();
- this->rigid.impulse_Linear += state.GetLinearImpulse();
- this->rigid.impulse_Angular += state.GetAngularImpulse();
- this->rigid.restitutionCoeff = state.GetRestitutionCoeff();
- this->rigid.frictionCoeff_Static = state.GetFrictionCoeff_Static();
- this->rigid.frictionCoeff_Kinetic = state.GetFrictionCoeff_Kinetic();
- this->rigid.SetMass_KeepMomentum( state.GetMass() );
- this->rigid.SetMomentOfInertia_KeepMomentum( state.GetMomentOfInertia() );
- this->rigid.gravityNormal = state.GetGravityNormal();
+ btTransform trans;
+ btVector3 position(state.centerPos.x, state.centerPos.y, state.centerPos.z);
+ btQuaternion quaternion(state.quaternion.imaginary.x, state.quaternion.imaginary.y, state.quaternion.imaginary.z, state.quaternion.real);
+ this->motionState->getWorldTransform(trans);
+ trans.setRotation(quaternion);
+ trans.setOrigin(position);
+ this->motionState->setWorldTransform(trans);
+ this->rigidBody->setFriction(state.staticFrictionCoeff);
+ this->rigidBody->setRestitution(state.restitutionCoeff);
+ btVector3 fallInertia(0, 0, 0);
+ collisionShape->calculateLocalInertia(state.mass, fallInertia);
+ this->rigidBody->setMassProps(state.mass, fallInertia);
- if( state.IsForwarded() )
- {
- this->deltaPos += Float4(state.GetForward_DeltaPos(), 0);
- this->deltaAxis += Float4(state.GetForward_DeltaAxis(), 0);
- this->isForwarded;
- }
-
- if( this->scene )
- {
- if( state.IsSpatiallyAltered() )
- {
- unsigned int tempRef = this->scene->GetTemporaryReferenceOf( this );
- this->scene->SetAsAltered( tempRef );
- this->scene->EvaluatePosition( tempRef );
- }
- else if( state.IsDisturbed() )
- {
- this->scene->SetAsAltered( this->scene->GetTemporaryReferenceOf(this) );
- }
- }
+ this->state = state;
}
-ICustomBody::SubscriptMessage SimpleRigidBody::CallSubscription_BeforeCollisionResponse( const ICustomBody *deuter )
+void SimpleRigidBody::SetCollisionShape(btCollisionShape* shape)
{
- return this->onCollision( this, deuter );
+ this->collisionShape = shape;
}
-void SimpleRigidBody::CallSubscription_AfterCollisionResponse( const ICustomBody *deuter, Float kineticEnergyLoss )
+void SimpleRigidBody::SetMotionState(btDefaultMotionState* motionState)
{
- return this->onCollisionResponse( this, deuter, kineticEnergyLoss );
+ this->motionState = motionState;
+}
+
+void SimpleRigidBody::SetRigidBody(btRigidBody* rigidBody)
+{
+ this->rigidBody = rigidBody;
+
+}
+
+void SimpleRigidBody::SetSubscription(EventAction_AfterCollisionResponse function)
+{
+ this->afterCollision = function;
+}
+
+void SimpleRigidBody::SetSubscription(EventAction_Move function)
+{
+ this->onMovement = function;
+}
+
+void SimpleRigidBody::SetLinearVelocity(Float3 velocity)
+{
+ this->rigidBody->setLinearVelocity(btVector3(velocity.x, velocity.y, velocity.z));
+}
+
+void SimpleRigidBody::SetPosition(::Oyster::Math::Float3 position)
+{
+ btTransform trans;
+ this->motionState->getWorldTransform(trans);
+ trans.setOrigin(btVector3(position.x, position.y, position.z));
+ this->motionState->setWorldTransform(trans);
+ this->state.centerPos = position;
+}
+
+void SimpleRigidBody::SetRotation(Float4 quaternion)
+{
+ btTransform trans;
+ this->motionState->getWorldTransform(trans);
+ trans.setRotation(btQuaternion(quaternion.x, quaternion.y, quaternion.z, quaternion.w));
+ this->motionState->setWorldTransform(trans);
+ this->state.quaternion = Quaternion(quaternion.xyz, quaternion.w);
+}
+
+void SimpleRigidBody::SetRotation(::Oyster::Math::Quaternion quaternion)
+{
+ btTransform trans;
+ this->motionState->getWorldTransform(trans);
+ trans.setRotation(btQuaternion(quaternion.imaginary.x, quaternion.imaginary.y, quaternion.imaginary.z, quaternion.real));
+ this->motionState->setWorldTransform(trans);
+ this->state.quaternion = quaternion;
+}
+
+void SimpleRigidBody::SetRotation(Float3 eulerAngles)
+{
+ btTransform trans;
+ this->motionState->getWorldTransform(trans);
+ trans.setRotation(btQuaternion(eulerAngles.x, eulerAngles.y, eulerAngles.z));
+ this->motionState->setWorldTransform(trans);
+ this->state.quaternion = Quaternion(Float3(trans.getRotation().x(), trans.getRotation().y(), trans.getRotation().z()), trans.getRotation().w());
+}
+
+Float4x4 SimpleRigidBody::GetRotation() const
+{
+ return this->state.GetRotation();
+}
+
+Float4x4 SimpleRigidBody::GetOrientation() const
+{
+ return this->state.GetOrientation();
+}
+
+Float4x4 SimpleRigidBody::GetView() const
+{
+ return this->state.GetView();
+}
+
+Float4x4 SimpleRigidBody::GetView( const ::Oyster::Math::Float3 &offset ) const
+{
+ return this->state.GetView(offset);
+}
+
+void SimpleRigidBody::CallSubscription_AfterCollisionResponse(ICustomBody* bodyA, ICustomBody* bodyB, Oyster::Math::Float kineticEnergyLoss)
+{
+ if(this->afterCollision)
+ this->afterCollision(bodyA, bodyB, kineticEnergyLoss);
}
void SimpleRigidBody::CallSubscription_Move()
{
- this->onMovement( this );
+ if(this->onMovement)
+ this->onMovement(this);
}
-bool SimpleRigidBody::IsAffectedByGravity() const
+btCollisionShape* SimpleRigidBody::GetCollisionShape() const
{
- return !this->ignoreGravity;
+ return this->collisionShape;
}
-bool SimpleRigidBody::Intersects( const ICollideable &shape ) const
+btDefaultMotionState* SimpleRigidBody::GetMotionState() const
{
- return Box( this->rigid.GetRotationMatrix(), this->rigid.centerPos, this->rigid.GetSize() ).Intersects( shape );
+ return this->motionState;
}
-bool SimpleRigidBody::Intersects( const ICollideable &shape, Float4 &worldPointOfContact ) const
+btRigidBody* SimpleRigidBody::GetRigidBody() const
{
- return Box( this->rigid.GetRotationMatrix(), this->rigid.centerPos, this->rigid.GetSize() ).Intersects( shape, worldPointOfContact );
-}
-
-bool SimpleRigidBody::Intersects( const ICustomBody &object, Float4 &worldPointOfContact ) const
-{
- return object.Intersects( Box(this->rigid.GetRotationMatrix(), this->rigid.centerPos, this->rigid.GetSize()), worldPointOfContact );
-}
-
-void SimpleRigidBody::SetTimeOfContact( Float4 &worldPointOfContact )
-{
- Point pointOfContact = Point( worldPointOfContact );
- Box start = Box();
- {
- start.rotation = RotationMatrix( this->collisionRebound.previousSpatial.axis );
- start.center = this->collisionRebound.previousSpatial.center;
- start.boundingOffset = this->collisionRebound.previousSpatial.reach;
- }
- Box end = Box();
- {
- end.rotation = RotationMatrix( this->rigid.axis );
- end.center = this->rigid.centerPos;
- end.boundingOffset = this->rigid.boundingReach;
- }
- Float timeOfContact = ::Oyster::Collision3D::Utility::TimeOfContact( start, end, pointOfContact );
-
- this->collisionRebound.timeOfContact = Min( this->collisionRebound.timeOfContact, timeOfContact );
-}
-
-Sphere & SimpleRigidBody::GetBoundingSphere( Sphere &targetMem ) const
-{
- return targetMem = Sphere( this->rigid.centerPos, this->rigid.boundingReach.GetMagnitude() );
-}
-
-Float4 & SimpleRigidBody::GetNormalAt( const Float4 &worldPos, Float4 &targetMem ) const
-{
- Float4 offset = worldPos.xyz - this->rigid.centerPos;
- Float distance = offset.Dot( offset );
- Float3 normal = Float3::null;
-
- if( distance != 0.0f )
- { // sanity check
- Ray axis( Float4::standard_unit_w, offset / (Float)::std::sqrt(distance) );
- Float minDistance = numeric_limits::max();
- Float4x4 rotationMatrix = this->rigid.GetRotationMatrix();
-
- if( Private::Intersects(axis, Plane(rotationMatrix.v[0], -this->rigid.boundingReach.x), axis.collisionDistance) )
- { // check along x-axis
- if( axis.collisionDistance < 0.0f )
- normal = -rotationMatrix.v[0].xyz;
- else
- normal = rotationMatrix.v[0].xyz;
-
- minDistance = Abs( axis.collisionDistance );
- }
-
- if( Private::Intersects(axis, Plane(rotationMatrix.v[1], -this->rigid.boundingReach.y), axis.collisionDistance) )
- { // check along y-axis
- distance = Abs( axis.collisionDistance ); // recycling memory
- if( minDistance > distance )
- {
- if( axis.collisionDistance < 0.0f )
- normal = -rotationMatrix.v[1].xyz;
- else
- normal = rotationMatrix.v[1].xyz;
-
- minDistance = distance;
- }
- }
-
- if( Private::Intersects(axis, Plane(rotationMatrix.v[2], -this->rigid.boundingReach.z), axis.collisionDistance) )
- { // check along z-axis
- if( minDistance > Abs( axis.collisionDistance ) )
- {
- if( axis.collisionDistance < 0.0f )
- normal = -rotationMatrix.v[2].xyz;
- else
- normal = rotationMatrix.v[2].xyz;
- }
- }
- }
- targetMem.xyz = normal;
- targetMem.w = 0.0f;
- return targetMem;
-}
-
-Float3 & SimpleRigidBody::GetGravityNormal( Float3 &targetMem ) const
-{
- return targetMem = this->gravityNormal;
+ return this->rigidBody;
}
void * SimpleRigidBody::GetCustomTag() const
@@ -300,182 +186,10 @@ void * SimpleRigidBody::GetCustomTag() const
return this->customTag;
}
-//Float3 & SimpleRigidBody::GetCenter( Float3 &targetMem ) const
-//{
-// return targetMem = this->rigid.centerPos;
-//}
-//
-//Float4x4 & SimpleRigidBody::GetRotation( Float4x4 &targetMem ) const
-//{
-// return targetMem = this->rigid.box.rotation;
-//}
-//
-//Float4x4 & SimpleRigidBody::GetOrientation( Float4x4 &targetMem ) const
-//{
-// return targetMem = this->rigid.GetOrientation();
-//}
-//
-//Float4x4 & SimpleRigidBody::GetView( Float4x4 &targetMem ) const
-//{
-// return targetMem = this->rigid.GetView();
-//}
-
-//Float3 SimpleRigidBody::GetRigidLinearVelocity() const
-//{
-// return this->rigid.GetLinearVelocity();
-//}
-
-UpdateState SimpleRigidBody::Update( Float timeStepLength )
-{
- if( this->collisionRebound.timeOfContact < 1.0f )
- { // Rebound if needed
- this->rigid.centerPos = Lerp( this->collisionRebound.previousSpatial.center, this->rigid.centerPos, this->collisionRebound.timeOfContact );
- this->rigid.SetRotation( Lerp(this->collisionRebound.previousSpatial.axis, this->rigid.axis, this->collisionRebound.timeOfContact) );
- this->rigid.boundingReach = Lerp( this->collisionRebound.previousSpatial.reach, this->rigid.boundingReach, this->collisionRebound.timeOfContact );
- timeStepLength *= 2.0f - this->collisionRebound.timeOfContact; // compensate for rebounded time
- this->collisionRebound.timeOfContact = 1.0f;
- }
-
- // Maintain rotation resolution by keeping axis within [0, 2pi] (trigonometric methods gets faster too)
- Float4 temp;
- ::std::modf( this->rigid.axis * (0.5f / pi), temp.xyz );
- this->rigid.axis -= ((2.0f * pi) * temp).xyz;
-
- // Update rebound data
- this->collisionRebound.previousSpatial.center = this->rigid.centerPos;
- this->collisionRebound.previousSpatial.axis = this->rigid.axis;
- this->collisionRebound.previousSpatial.reach = this->rigid.boundingReach;
-
- // Check if this is close enough to be set resting
- temp = Float4( this->rigid.impulse_Linear, 0.0f ) + Float4( this->rigid.impulse_Angular, 0.0f );
- if( temp.Dot(temp) <= (Constant::epsilon * Constant::epsilon) )
- {
- unsigned char resting = 0;
- if( this->rigid.momentum_Linear.Dot(this->rigid.momentum_Linear) <= (Constant::epsilon * Constant::epsilon) )
- {
- this->rigid.momentum_Linear = Float3::null;
- resting = 1;
- }
- if( this->rigid.momentum_Angular.Dot(this->rigid.momentum_Angular) <= (Constant::epsilon * Constant::epsilon) )
- {
- this->rigid.momentum_Angular = Float3::null;
- ++resting;
- }
- if( resting == 2 )
- {
- this->rigid.impulse_Linear = this->rigid.impulse_Angular = Float3::null;
- return UpdateState_resting;
- }
- }
-
- this->rigid.Update_LeapFrog( timeStepLength );
- return UpdateState_altered;
-}
-
-void SimpleRigidBody::Predict( Float4 &outDeltaPos, Float4 &outDeltaAxis, const Float4 &actingLinearImpulse, const Float4 &actingAngularImpulse, Float deltaTime )
-{
- this->rigid.Predict_LeapFrog( outDeltaPos.xyz, outDeltaAxis.xyz, actingLinearImpulse.xyz, actingAngularImpulse.xyz, deltaTime );
-}
-
-void SimpleRigidBody::SetScene( void *scene )
-{
- this->scene = (Octree*)scene;
-}
-
-void SimpleRigidBody::SetSubscription( ICustomBody::EventAction_BeforeCollisionResponse functionPointer )
-{
- if( functionPointer )
- {
- this->onCollision = functionPointer;
- }
- else
- {
- this->onCollision = Default::EventAction_BeforeCollisionResponse;
- }
-}
-
-void SimpleRigidBody::SetSubscription( ICustomBody::EventAction_AfterCollisionResponse functionPointer )
-{
- if( functionPointer )
- {
- this->onCollisionResponse = functionPointer;
- }
- else
- {
- this->onCollisionResponse = Default::EventAction_AfterCollisionResponse;
- }
-}
-
-void SimpleRigidBody::SetSubscription( ICustomBody::EventAction_Move functionPointer )
-{
- if( functionPointer )
- {
- this->onMovement = functionPointer;
- }
- else
- {
- this->onMovement = Default::EventAction_Move;
- }
-}
-
-void SimpleRigidBody::SetGravity( bool ignore)
-{
- this->ignoreGravity = ignore;
- this->gravityNormal = Float3::null;
-}
-
-void SimpleRigidBody::SetGravityNormal( const Float3 &normalizedVector )
-{
- this->gravityNormal = normalizedVector;
- this->rigid.gravityNormal = Float4( this->gravityNormal, 0 );
-}
void SimpleRigidBody::SetCustomTag( void *ref )
{
this->customTag = ref;
}
-//void SimpleRigidBody::SetMomentOfInertiaTensor_KeepVelocity( const Float4x4 &localI )
-//{
-// this->rigid.SetMomentOfInertia_KeepVelocity( localI );
-//}
-//
-//void SimpleRigidBody::SetMomentOfInertiaTensor_KeepMomentum( const Float4x4 &localI )
-//{
-// this->rigid.SetMomentOfInertia_KeepMomentum( localI );
-//}
-//
-//void SimpleRigidBody::SetMass_KeepVelocity( Float m )
-//{
-// this->rigid.SetMass_KeepVelocity( m );
-//}
-//
-//void SimpleRigidBody::SetMass_KeepMomentum( Float m )
-//{
-// this->rigid.SetMass_KeepMomentum( m );
-//}
-//
-//void SimpleRigidBody::SetCenter( const Float3 &worldPos )
-//{
-// this->rigid.SetCenter( worldPos );
-//}
-//
-//void SimpleRigidBody::SetRotation( const Float4x4 &rotation )
-//{
-// this->rigid.SetRotation( rotation );
-//}
-//
-//void SimpleRigidBody::SetOrientation( const Float4x4 &orientation )
-//{
-// this->rigid.SetOrientation( orientation );
-//}
-//
-//void SimpleRigidBody::SetSize( const Float3 &size )
-//{
-// this->rigid.SetSize( size );
-//}
-//
-//void SimpleRigidBody::SetMomentum( const Float3 &worldG )
-//{
-// this->rigid.SetLinearMomentum( worldG );
-//}
+
diff --git a/Code/GamePhysics/Implementation/SimpleRigidBody.h b/Code/GamePhysics/Implementation/SimpleRigidBody.h
index 1811c911..55ae4fe3 100644
--- a/Code/GamePhysics/Implementation/SimpleRigidBody.h
+++ b/Code/GamePhysics/Implementation/SimpleRigidBody.h
@@ -2,86 +2,63 @@
#define OYSTER_PHYSICS_SIMPLE_RIGIDBODY_H
#include "..\PhysicsAPI.h"
-#include "RigidBody.h"
-#include "Octree.h"
+#include
-namespace Oyster { namespace Physics
-{
- class SimpleRigidBody : public ICustomBody
+namespace Oyster
+{
+ namespace Physics
{
- public:
- SimpleRigidBody();
- SimpleRigidBody( const API::SimpleBodyDescription &desc );
- virtual ~SimpleRigidBody();
-
- ::Utility::DynamicMemory::UniquePointer Clone() const;
-
- State GetState() const;
- State & GetState( State &targetMem ) const;
- void SetState( const State &state );
- //::Oyster::Math::Float3 GetRigidLinearVelocity() const;
-
- SubscriptMessage CallSubscription_BeforeCollisionResponse( const ICustomBody *deuter );
- void CallSubscription_AfterCollisionResponse( const ICustomBody *deuter, ::Oyster::Math::Float kineticEnergyLoss );
- void CallSubscription_Move();
-
- bool IsAffectedByGravity() const;
- bool Intersects( const ::Oyster::Collision3D::ICollideable &shape ) const;
- bool Intersects( const ::Oyster::Collision3D::ICollideable &shape, ::Oyster::Math::Float4 &worldPointOfContact ) const;
- bool Intersects( const ICustomBody &object, ::Oyster::Math::Float4 &worldPointOfContact ) const;
-
- void SetTimeOfContact( ::Oyster::Math::Float4 &worldPointOfContact );
-
- ::Oyster::Collision3D::Sphere & GetBoundingSphere( ::Oyster::Collision3D::Sphere &targetMem = ::Oyster::Collision3D::Sphere() ) const;
- ::Oyster::Math::Float4 & GetNormalAt( const ::Oyster::Math::Float4 &worldPos, ::Oyster::Math::Float4 &targetMem = ::Oyster::Math::Float4() ) const;
- ::Oyster::Math::Float3 & GetGravityNormal( ::Oyster::Math::Float3 &targetMem = ::Oyster::Math::Float3() ) const;
- void * GetCustomTag() const;
- //::Oyster::Math::Float3 & GetCenter( ::Oyster::Math::Float3 &targetMem = ::Oyster::Math::Float3() ) const;
- //::Oyster::Math::Float4x4 & GetRotation( ::Oyster::Math::Float4x4 &targetMem = ::Oyster::Math::Float4x4() ) const;
- //::Oyster::Math::Float4x4 & GetOrientation( ::Oyster::Math::Float4x4 &targetMem = ::Oyster::Math::Float4x4() ) const;
- //::Oyster::Math::Float4x4 & GetView( ::Oyster::Math::Float4x4 &targetMem = ::Oyster::Math::Float4x4() ) const;
-
- UpdateState Update( ::Oyster::Math::Float timeStepLength );
- void Predict( ::Oyster::Math::Float4 &outDeltaPos, ::Oyster::Math::Float4 &outDeltaAxis, const ::Oyster::Math::Float4 &actingLinearImpulse, const ::Oyster::Math::Float4 &actingAngularImpulse, ::Oyster::Math::Float deltaTime );
-
- void SetScene( void *scene );
-
- void SetSubscription( EventAction_BeforeCollisionResponse functionPointer );
- void SetSubscription( EventAction_AfterCollisionResponse functionPointer );
- void SetSubscription( EventAction_Move functionPointer );
-
- void SetGravity( bool ignore);
- void SetGravityNormal( const ::Oyster::Math::Float3 &normalizedVector );
- void SetCustomTag( void *ref );
- //void SetMomentOfInertiaTensor_KeepVelocity( const ::Oyster::Math::Float4x4 &localI );
- //void SetMomentOfInertiaTensor_KeepMomentum( const ::Oyster::Math::Float4x4 &localI );
- //void SetMass_KeepVelocity( ::Oyster::Math::Float m );
- //void SetMass_KeepMomentum( ::Oyster::Math::Float m );
- //void SetCenter( const ::Oyster::Math::Float3 &worldPos );
- //void SetRotation( const ::Oyster::Math::Float4x4 &rotation );
- //void SetOrientation( const ::Oyster::Math::Float4x4 &orientation );
- //void SetSize( const ::Oyster::Math::Float3 &size );
- //void SetMomentum( const ::Oyster::Math::Float3 &worldG );
-
- private:
- ::Oyster::Physics3D::RigidBody rigid;
- ::Oyster::Math::Float4 deltaPos, deltaAxis;
- ::Oyster::Math::Float3 gravityNormal;
-
- struct
+ class SimpleRigidBody : public ICustomBody
{
- struct { ::Oyster::Math::Float3 center, axis, reach; } previousSpatial;
- ::Oyster::Math::Float timeOfContact;
- } collisionRebound;
+ public:
+ SimpleRigidBody();
+ virtual ~SimpleRigidBody();
- EventAction_BeforeCollisionResponse onCollision;
- EventAction_AfterCollisionResponse onCollisionResponse;
- EventAction_Move onMovement;
+ State GetState() const;
+ State& GetState( State &targetMem ) const;
+ void SetState( const State &state );
- Octree *scene;
- void *customTag;
- bool ignoreGravity, isForwarded;
- };
-} }
+ void SetCollisionShape(btCollisionShape* shape);
+ void SetMotionState(btDefaultMotionState* motionState);
+ void SetRigidBody(btRigidBody* rigidBody);
+
+ void SetSubscription(EventAction_AfterCollisionResponse function);
+ void SetSubscription(EventAction_Move function);
+
+ void SetLinearVelocity(Math::Float3 velocity);
+ void SetPosition(::Oyster::Math::Float3 position);
+ void SetRotation(Math::Float4 quaternion);
+ void SetRotation(::Oyster::Math::Quaternion quaternion);
+ void SetRotation(Math::Float3 eulerAngles);
+
+ Math::Float4x4 GetRotation() const;
+ Math::Float4x4 GetOrientation() const;
+ Math::Float4x4 GetView() const;
+ Math::Float4x4 GetView( const ::Oyster::Math::Float3 &offset ) const;
+
+ void CallSubscription_AfterCollisionResponse(ICustomBody* bodyA, ICustomBody* bodyB, Math::Float kineticEnergyLoss);
+ void CallSubscription_Move();
+
+ btCollisionShape* GetCollisionShape() const;
+ btDefaultMotionState* GetMotionState() const;
+ btRigidBody* GetRigidBody() const;
+
+ void SetCustomTag( void *ref );
+ void* GetCustomTag() const;
+
+ private:
+ btCollisionShape* collisionShape;
+ btDefaultMotionState* motionState;
+ btRigidBody* rigidBody;
+
+ Struct::CustomBodyState state;
+
+ EventAction_AfterCollisionResponse afterCollision;
+ EventAction_Move onMovement;
+
+ void *customTag;
+ };
+ }
+}
#endif
\ No newline at end of file
diff --git a/Code/GamePhysics/Implementation/SphericalRigidBody.cpp b/Code/GamePhysics/Implementation/SphericalRigidBody.cpp
index ac566abd..e69de29b 100644
--- a/Code/GamePhysics/Implementation/SphericalRigidBody.cpp
+++ b/Code/GamePhysics/Implementation/SphericalRigidBody.cpp
@@ -1,405 +0,0 @@
-#include "SphericalRigidBody.h"
-#include "PhysicsAPI_Impl.h"
-
-using namespace ::Oyster::Physics;
-using namespace ::Oyster::Physics3D;
-using namespace ::Oyster::Math3D;
-using namespace ::Oyster::Collision3D;
-using namespace ::Utility::DynamicMemory;
-using namespace ::Utility::Value;
-
-SphericalRigidBody::SphericalRigidBody()
-{
- this->rigid = RigidBody();
- this->rigid.SetMass_KeepMomentum( 16.0f );
- this->gravityNormal = Float3::null;
- this->onCollision = Default::EventAction_BeforeCollisionResponse;
- this->onCollisionResponse = Default::EventAction_AfterCollisionResponse;
- this->onMovement = Default::EventAction_Move;
-
- this->collisionRebound.previousSpatial.center = this->rigid.centerPos;
- this->collisionRebound.previousSpatial.axis = this->rigid.axis;
- this->collisionRebound.previousSpatial.reach = this->rigid.boundingReach;
- this->collisionRebound.timeOfContact = 1.0f;
-
- this->scene = nullptr;
- this->customTag = nullptr;
- this->ignoreGravity = this->isForwarded = false;
-}
-
-SphericalRigidBody::SphericalRigidBody( const API::SphericalBodyDescription &desc )
-{
- this->rigid = RigidBody();
- this->rigid.SetRotation( desc.rotation );
- this->rigid.centerPos = desc.centerPosition;
- this->rigid.boundingReach = Float4( desc.radius, desc.radius, desc.radius, 0.0f );
- this->rigid.restitutionCoeff = desc.restitutionCoeff;
- this->rigid.frictionCoeff_Static = desc.frictionCoeff_Static;
- this->rigid.frictionCoeff_Kinetic = desc.frictionCoeff_Dynamic;
- this->rigid.SetMass_KeepMomentum( desc.mass );
- this->rigid.SetMomentOfInertia_KeepMomentum( MomentOfInertia::Sphere(desc.mass, desc.radius) );
- this->deltaPos = Float4::null;
- this->deltaAxis = Float4::null;
-
- this->gravityNormal = Float3::null;
-
- this->collisionRebound.previousSpatial.center = this->rigid.centerPos;
- this->collisionRebound.previousSpatial.axis = this->rigid.axis;
- this->collisionRebound.previousSpatial.reach = this->rigid.boundingReach;
- this->collisionRebound.timeOfContact = 1.0f;
-
- if( desc.subscription_onCollision )
- {
- this->onCollision = desc.subscription_onCollision;
- }
- else
- {
- this->onCollision = Default::EventAction_BeforeCollisionResponse;
- }
-
- if( desc.subscription_onCollisionResponse )
- {
- this->onCollisionResponse = desc.subscription_onCollisionResponse;
- }
- else
- {
- this->onCollisionResponse = Default::EventAction_AfterCollisionResponse;
- }
-
- if( desc.subscription_onMovement )
- {
- this->onMovement= desc.subscription_onMovement;
- }
- else
- {
- this->onMovement = Default::EventAction_Move;
- }
-
- this->scene = nullptr;
- this->customTag = nullptr;
- this->ignoreGravity = desc.ignoreGravity;
-
- this->collisionRebound.previousSpatial.center = this->rigid.centerPos;
- this->collisionRebound.previousSpatial.axis = this->rigid.axis;
- this->collisionRebound.previousSpatial.reach = this->rigid.boundingReach;
- this->collisionRebound.timeOfContact = 1.0f;
-}
-
-SphericalRigidBody::~SphericalRigidBody() {}
-
-UniquePointer SphericalRigidBody::Clone() const
-{
- return new SphericalRigidBody( *this );
-}
-
-SphericalRigidBody::State SphericalRigidBody::GetState() const
-{
- return State( this->rigid.GetMass(), this->rigid.restitutionCoeff,
- this->rigid.frictionCoeff_Static, this->rigid.frictionCoeff_Kinetic,
- this->rigid.GetMomentOfInertia(), this->rigid.boundingReach,
- this->rigid.centerPos, this->rigid.axis,
- this->rigid.momentum_Linear, this->rigid.momentum_Angular );
-}
-
-SphericalRigidBody::State & SphericalRigidBody::GetState( SphericalRigidBody::State &targetMem ) const
-{
- return targetMem = State( this->rigid.GetMass(), this->rigid.restitutionCoeff,
- this->rigid.frictionCoeff_Static, this->rigid.frictionCoeff_Kinetic,
- this->rigid.GetMomentOfInertia(), this->rigid.boundingReach,
- this->rigid.centerPos, this->rigid.axis,
- this->rigid.momentum_Linear, this->rigid.momentum_Angular );
-}
-
-void SphericalRigidBody::SetState( const SphericalRigidBody::State &state )
-{
- this->rigid.centerPos = state.GetCenterPosition();
- this->rigid.axis = state.GetAngularAxis();
- this->rigid.boundingReach = state.GetReach();
- this->rigid.momentum_Linear = state.GetLinearMomentum();
- this->rigid.momentum_Angular = state.GetAngularMomentum();
- this->rigid.impulse_Linear += state.GetLinearImpulse();
- this->rigid.impulse_Angular += state.GetAngularImpulse();
- this->rigid.restitutionCoeff = state.GetRestitutionCoeff();
- this->rigid.frictionCoeff_Static = state.GetFrictionCoeff_Static();
- this->rigid.frictionCoeff_Kinetic = state.GetFrictionCoeff_Kinetic();
- this->rigid.SetMass_KeepMomentum( state.GetMass() );
- this->rigid.SetMomentOfInertia_KeepMomentum( state.GetMomentOfInertia() );
- this->rigid.gravityNormal = state.GetGravityNormal();
-
- if( state.IsForwarded() )
- {
- this->deltaPos += Float4(state.GetForward_DeltaPos(), 0);
- this->deltaAxis += Float4(state.GetForward_DeltaAxis());
- this->isForwarded = false;
- }
-
- if( this->scene )
- {
- if( state.IsSpatiallyAltered() )
- {
- unsigned int tempRef = this->scene->GetTemporaryReferenceOf( this );
- this->scene->SetAsAltered( tempRef );
- this->scene->EvaluatePosition( tempRef );
- }
- else if( state.IsDisturbed() )
- {
- this->scene->SetAsAltered( this->scene->GetTemporaryReferenceOf(this) );
- }
- }
-}
-
-ICustomBody::SubscriptMessage SphericalRigidBody::CallSubscription_BeforeCollisionResponse( const ICustomBody *deuter )
-{
- return this->onCollision( this, deuter );
-}
-
-void SphericalRigidBody::CallSubscription_AfterCollisionResponse( const ICustomBody *deuter, Float kineticEnergyLoss )
-{
- this->onCollisionResponse( this, deuter, kineticEnergyLoss);
-}
-
-
-void SphericalRigidBody::CallSubscription_Move()
-{
- this->onMovement( this );
-}
-
-bool SphericalRigidBody::IsAffectedByGravity() const
-{
- return !this->ignoreGravity;
-}
-
-bool SphericalRigidBody::Intersects( const ICollideable &shape ) const
-{
- return Sphere( this->rigid.centerPos, this->rigid.boundingReach.x ).Intersects( shape );
-}
-
-bool SphericalRigidBody::Intersects( const ICollideable &shape, Float4 &worldPointOfContact ) const
-{
- return Sphere( this->rigid.centerPos, this->rigid.boundingReach.x ).Intersects( shape, worldPointOfContact );
-}
-
-bool SphericalRigidBody::Intersects( const ICustomBody &object, Float4 &worldPointOfContact ) const
-{
- return object.Intersects( Sphere(this->rigid.centerPos, this->rigid.boundingReach.x), worldPointOfContact );
-}
-
-void SphericalRigidBody::SetTimeOfContact( Float4 &worldPointOfContact )
-{
- Point pointOfContact = Point( worldPointOfContact );
- Sphere start = Sphere( this->collisionRebound.previousSpatial.center, this->collisionRebound.previousSpatial.reach.x );
- Sphere end = Sphere( this->rigid.centerPos, this->rigid.boundingReach.x );
-
- Float timeOfContact = ::Oyster::Collision3D::Utility::TimeOfContact( start, end, pointOfContact );
-
- this->collisionRebound.timeOfContact = Min( this->collisionRebound.timeOfContact, timeOfContact );
-}
-
-Sphere & SphericalRigidBody::GetBoundingSphere( Sphere &targetMem ) const
-{
- return targetMem = Sphere( this->rigid.centerPos, this->rigid.boundingReach.x );
-}
-
-Float4 & SphericalRigidBody::GetNormalAt( const Float4 &worldPos, Float4 &targetMem ) const
-{
- targetMem = Float4( worldPos.xyz - this->rigid.centerPos, 0);
- Float magnitude = targetMem.GetMagnitude();
- if( magnitude != 0.0f )
- { // sanity check
- targetMem.Normalize();
- }
-
- return targetMem;
-}
-
-Float3 & SphericalRigidBody::GetGravityNormal( Float3 &targetMem ) const
-{
- return targetMem = this->gravityNormal;
-}
-
-void * SphericalRigidBody::GetCustomTag() const
-{
- return this->customTag;
-}
-
-//Float3 & SphericalRigidBody::GetCenter( Float3 &targetMem ) const
-//{
-// return targetMem = this->rigid.centerPos;
-//}
-//
-//Float4x4 & SphericalRigidBody::GetRotation( Float4x4 &targetMem ) const
-//{
-// return targetMem = this->rigid.box.rotation;
-//}
-//
-//Float4x4 & SphericalRigidBody::GetOrientation( Float4x4 &targetMem ) const
-//{
-// return targetMem = this->rigid.GetOrientation();
-//}
-//
-//Float4x4 & SphericalRigidBody::GetView( Float4x4 &targetMem ) const
-//{
-// return targetMem = this->rigid.GetView();
-//}
-
-//Float3 SphericalRigidBody::GetRigidLinearVelocity() const
-//{
-// return this->rigid.GetLinearVelocity();
-//}
-
-UpdateState SphericalRigidBody::Update( Float timeStepLength )
-{
- if( this->collisionRebound.timeOfContact < 1.0f )
- { // Rebound if needed
- this->rigid.centerPos = Lerp( this->collisionRebound.previousSpatial.center, this->rigid.centerPos, this->collisionRebound.timeOfContact );
- this->rigid.SetRotation( Lerp(this->collisionRebound.previousSpatial.axis, this->rigid.axis, this->collisionRebound.timeOfContact) );
- this->rigid.boundingReach = Lerp( this->collisionRebound.previousSpatial.reach, this->rigid.boundingReach, this->collisionRebound.timeOfContact );
- timeStepLength *= 2.0f - this->collisionRebound.timeOfContact; // compensate for rebounded time
- this->collisionRebound.timeOfContact = 1.0f;
- }
-
- // Maintain rotation resolution by keeping axis within [0, 2pi] (trigonometric methods gets faster too)
- Float4 temp;
- ::std::modf( this->rigid.axis * (0.5f / pi), temp.xyz );
- this->rigid.axis -= ((2.0f * pi) * temp).xyz;
-
- // Update rebound data
- this->collisionRebound.previousSpatial.center = this->rigid.centerPos;
- this->collisionRebound.previousSpatial.axis = this->rigid.axis;
- this->collisionRebound.previousSpatial.reach = this->rigid.boundingReach;
-
- // Check if this is close enough to be set resting
- temp = Float4( this->rigid.impulse_Linear, 0.0f ) + Float4( this->rigid.impulse_Angular, 0.0f );
- if( temp.Dot(temp) <= (Constant::epsilon * Constant::epsilon) )
- {
- unsigned char resting = 0;
- if( this->rigid.momentum_Linear.Dot(this->rigid.momentum_Linear) <= (Constant::epsilon * Constant::epsilon) )
- {
- this->rigid.momentum_Linear = Float3::null;
- resting = 1;
- }
- if( this->rigid.momentum_Angular.Dot(this->rigid.momentum_Angular) <= (Constant::epsilon * Constant::epsilon) )
- {
- this->rigid.momentum_Angular = Float3::null;
- ++resting;
- }
- if( resting == 2 )
- {
- this->rigid.impulse_Linear = this->rigid.impulse_Angular = Float3::null;
- return UpdateState_resting;
- }
- }
-
- this->rigid.Update_LeapFrog( timeStepLength );
- return UpdateState_altered;
-}
-
-void SphericalRigidBody::Predict( ::Oyster::Math::Float4 &outDeltaPos, ::Oyster::Math::Float4 &outDeltaAxis, const ::Oyster::Math::Float4 &actingLinearImpulse, const ::Oyster::Math::Float4 &actingAngularImpulse, ::Oyster::Math::Float deltaTime )
-{
- this->rigid.Predict_LeapFrog( outDeltaPos.xyz, outDeltaAxis.xyz, actingLinearImpulse.xyz, actingAngularImpulse.xyz, deltaTime );
-}
-
-void SphericalRigidBody::SetSubscription( ICustomBody::EventAction_BeforeCollisionResponse functionPointer )
-{
- if( functionPointer )
- {
- this->onCollision = functionPointer;
- }
- else
- {
- this->onCollision = Default::EventAction_BeforeCollisionResponse;
- }
-}
-
-void SphericalRigidBody::SetSubscription( ICustomBody::EventAction_AfterCollisionResponse functionPointer )
-{
- if( functionPointer )
- {
- this->onCollisionResponse = functionPointer;
- }
- else
- {
- this->onCollisionResponse = Default::EventAction_AfterCollisionResponse;
- }
-}
-
-void SphericalRigidBody::SetSubscription( ICustomBody::EventAction_Move functionPointer )
-{
- if( functionPointer )
- {
- this->onMovement = functionPointer;
- }
- else
- {
- this->onMovement = Default::EventAction_Move;
- }
-}
-
-void SphericalRigidBody::SetScene( void *scene )
-{
- this->scene = (Octree*)scene;
-}
-
-void SphericalRigidBody::SetGravity( bool ignore )
-{
- this->ignoreGravity = ignore;
- this->gravityNormal = Float3::null;
-}
-
-void SphericalRigidBody::SetGravityNormal( const Float3 &normalizedVector )
-{
- this->gravityNormal = normalizedVector;
-}
-
-void SphericalRigidBody::SetCustomTag( void *ref )
-{
- this->customTag = ref;
-}
-
-//void SphericalRigidBody::SetMomentOfInertiaTensor_KeepVelocity( const Float4x4 &localI )
-//{
-// this->rigid.SetMomentOfInertia_KeepVelocity( localI );
-//}
-//
-//void SphericalRigidBody::SetMomentOfInertiaTensor_KeepMomentum( const Float4x4 &localI )
-//{
-// this->rigid.SetMomentOfInertia_KeepMomentum( localI );
-//}
-//
-//void SphericalRigidBody::SetMass_KeepVelocity( Float m )
-//{
-// this->rigid.SetMass_KeepVelocity( m );
-//}
-//
-//void SphericalRigidBody::SetMass_KeepMomentum( Float m )
-//{
-// this->rigid.SetMass_KeepMomentum( m );
-//}
-//
-//void SphericalRigidBody::SetCenter( const Float3 &worldPos )
-//{
-// this->rigid.SetCenter( worldPos );
-// this->body.center = worldPos;
-//}
-//
-//void SphericalRigidBody::SetRotation( const Float4x4 &rotation )
-//{
-// this->rigid.SetRotation( rotation );
-//}
-//
-//void SphericalRigidBody::SetOrientation( const Float4x4 &orientation )
-//{
-// this->rigid.SetOrientation( orientation );
-// this->body.center = orientation.v[3].xyz;
-//}
-//
-//void SphericalRigidBody::SetSize( const Float3 &size )
-//{
-// this->rigid.SetSize( size );
-// this->body.radius = 0.5f * Min( Min( size.x, size.y ), size.z ); // inline Min( FloatN )?
-//}
-//
-//void SphericalRigidBody::SetMomentum( const Float3 &worldG )
-//{
-// this->rigid.SetLinearMomentum( worldG );
-//}
diff --git a/Code/GamePhysics/Implementation/SphericalRigidBody.h b/Code/GamePhysics/Implementation/SphericalRigidBody.h
index c2dc8131..e69de29b 100644
--- a/Code/GamePhysics/Implementation/SphericalRigidBody.h
+++ b/Code/GamePhysics/Implementation/SphericalRigidBody.h
@@ -1,87 +0,0 @@
-#ifndef OYSTER_PHYSICS_SPHERICAL_RIGIDBODY_H
-#define OYSTER_PHYSICS_SPHERICAL_RIGIDBODY_H
-
-#include "..\PhysicsAPI.h"
-#include "RigidBody.h"
-#include "Sphere.h"
-#include "Octree.h"
-
-namespace Oyster { namespace Physics
-{
- class SphericalRigidBody : public ICustomBody
- {
- public:
- SphericalRigidBody();
- SphericalRigidBody( const API::SphericalBodyDescription &desc );
- virtual ~SphericalRigidBody();
-
- ::Utility::DynamicMemory::UniquePointer Clone() const;
-
- State GetState() const;
- State & GetState( State &targetMem = State() ) const;
- void SetState( const State &state );
- //::Oyster::Math::Float3 GetRigidLinearVelocity() const;
-
- SubscriptMessage CallSubscription_BeforeCollisionResponse( const ICustomBody *deuter );
- void CallSubscription_AfterCollisionResponse( const ICustomBody *deuter, ::Oyster::Math::Float kineticEnergyLoss );
- void CallSubscription_Move();
-
- bool IsAffectedByGravity() const;
- bool Intersects( const ::Oyster::Collision3D::ICollideable &shape ) const;
- bool Intersects( const ::Oyster::Collision3D::ICollideable &shape, ::Oyster::Math::Float4 &worldPointOfContact ) const;
- bool Intersects( const ICustomBody &object, ::Oyster::Math::Float4 &worldPointOfContact ) const;
-
- void SetTimeOfContact( ::Oyster::Math::Float4 &worldPointOfContact );
-
- ::Oyster::Collision3D::Sphere & GetBoundingSphere( ::Oyster::Collision3D::Sphere &targetMem = ::Oyster::Collision3D::Sphere() ) const;
- ::Oyster::Math::Float4 & GetNormalAt( const ::Oyster::Math::Float4 &worldPos, ::Oyster::Math::Float4 &targetMem = ::Oyster::Math::Float4() ) const;
- ::Oyster::Math::Float3 & GetGravityNormal( ::Oyster::Math::Float3 &targetMem = ::Oyster::Math::Float3() ) const;
- void * GetCustomTag() const;
- //::Oyster::Math::Float3 & GetCenter( ::Oyster::Math::Float3 &targetMem = ::Oyster::Math::Float3() ) const;
- //::Oyster::Math::Float4x4 & GetRotation( ::Oyster::Math::Float4x4 &targetMem = ::Oyster::Math::Float4x4() ) const;
- //::Oyster::Math::Float4x4 & GetOrientation( ::Oyster::Math::Float4x4 &targetMem = ::Oyster::Math::Float4x4() ) const;
- //::Oyster::Math::Float4x4 & GetView( ::Oyster::Math::Float4x4 &targetMem = ::Oyster::Math::Float4x4() ) const;
-
- UpdateState Update( ::Oyster::Math::Float timeStepLength );
- void Predict( ::Oyster::Math::Float4 &outDeltaPos, ::Oyster::Math::Float4 &outDeltaAxis, const ::Oyster::Math::Float4 &actingLinearImpulse, const ::Oyster::Math::Float4 &actingAngularImpulse, ::Oyster::Math::Float deltaTime );
-
- void SetScene( void *scene );
-
- void SetSubscription( EventAction_BeforeCollisionResponse functionPointer );
- void SetSubscription( EventAction_AfterCollisionResponse functionPointer );
- void SetSubscription( EventAction_Move functionPointer );
-
- void SetGravity( bool ignore);
- void SetGravityNormal( const ::Oyster::Math::Float3 &normalizedVector );
- void SetCustomTag( void *ref );
- //void SetMomentOfInertiaTensor_KeepVelocity( const ::Oyster::Math::Float4x4 &localI );
- //void SetMomentOfInertiaTensor_KeepMomentum( const ::Oyster::Math::Float4x4 &localI );
- //void SetMass_KeepVelocity( ::Oyster::Math::Float m );
- //void SetMass_KeepMomentum( ::Oyster::Math::Float m );
- //void SetCenter( const ::Oyster::Math::Float3 &worldPos );
- //void SetRotation( const ::Oyster::Math::Float4x4 &rotation );
- //void SetOrientation( const ::Oyster::Math::Float4x4 &orientation );
- //void SetSize( const ::Oyster::Math::Float3 &size );
- //void SetMomentum( const ::Oyster::Math::Float3 &worldG );
-
- private:
- ::Oyster::Physics3D::RigidBody rigid;
- ::Oyster::Math::Float4 deltaPos, deltaAxis;
- ::Oyster::Math::Float3 gravityNormal;
-
- struct
- {
- struct { ::Oyster::Math::Float3 center, axis, reach; } previousSpatial;
- ::Oyster::Math::Float timeOfContact;
- } collisionRebound;
-
- EventAction_BeforeCollisionResponse onCollision;
- EventAction_AfterCollisionResponse onCollisionResponse;
- EventAction_Move onMovement;
- Octree *scene;
- void *customTag;
- bool ignoreGravity, isForwarded;
- };
-} }
-
-#endif
\ No newline at end of file
diff --git a/Code/GamePhysics/PhysicsAPI.h b/Code/GamePhysics/PhysicsAPI.h
index c3efef3e..f57fe130 100644
--- a/Code/GamePhysics/PhysicsAPI.h
+++ b/Code/GamePhysics/PhysicsAPI.h
@@ -55,35 +55,7 @@ namespace Oyster
* @param numGravityWells: The predicted max number of active gravity wells.
* @param worldSize: The size of acceptable physics space.
********************************************************/
- virtual void Init( unsigned int numObjects, unsigned int numGravityWells , const ::Oyster::Math::Float3 &worldSize ) = 0;
-
- /********************************************************
- * Sets the time length of each physics update frame.
- ********************************************************/
- virtual void SetFrameTimeLength( float seconds ) = 0;
-
- /********************************************************
- * Sets the Gravityconstant in the physics that will be
- * used in ForceField calculations.
- * @param g: Default is the real world Constant::gravity_constant [N(m/kg)^2]
- ********************************************************/
- virtual void SetGravityConstant( float g ) = 0;
-
- /********************************************************
- * Sets the function that will be called by the engine
- * whenever an object is being destroyed for some reason.
- * - Because DestroyObject(...) were called.
- * - Out of memory forced engine to destroy an object.
- * @param functionPointer: If NULL, an empty default function will be set.
- ********************************************************/
- virtual void SetSubscription( EventAction_Destruction functionPointer ) = 0;
-
- /********************************************************
- * Triggers the engine to run next update frame.
- * All accumulated forces and changes will be consumed.
- * EventAction functions might be called.
- ********************************************************/
- virtual void Update() = 0;
+ virtual void Init() = 0;
/********************************************************
* An object in limbo state will be ignored during the physics frame Update.
@@ -106,36 +78,15 @@ namespace Oyster
********************************************************/
virtual void ReleaseFromLimbo( const ICustomBody* objRef ) = 0;
- /********************************************************
- * Introduces a new object into the engine.
- * @param handle: A pointer along with the responsibility to delete.
- ********************************************************/
- virtual void AddObject( ::Utility::DynamicMemory::UniquePointer handle ) = 0;
- /********************************************************
- * Fetches and removes an object from the engine.
- * Will not call the provided EventAction_Destruction method.
- * @param objRef: A pointer to the ICustomBody representing a physical object.
- * @return A pointer along with the responsibility to delete. NULL if faulty objRef.
- ********************************************************/
- virtual ::Utility::DynamicMemory::UniquePointer ExtractObject( const ICustomBody* objRef ) = 0;
+ // Bullet physics
+ virtual ICustomBody* AddCollisionSphere(float radius, ::Oyster::Math::Float4 rotation, ::Oyster::Math::Float3 position, float mass, float restitution, float staticFriction, float dynamicFriction) = 0;
+ virtual ICustomBody* AddCollisionBox(::Oyster::Math::Float3 halfSize, ::Oyster::Math::Float4 rotation, ::Oyster::Math::Float3 position, float mass, float restitution, float staticFriction, float dynamicFriction) = 0;
+ virtual ICustomBody* AddCollisionCylinder(::Oyster::Math::Float3 halfSize, ::Oyster::Math::Float4 rotation, ::Oyster::Math::Float3 position, float mass, float restitution, float staticFriction, float dynamicFriction) = 0;
- /********************************************************
- * Removes an object from the engine.
- * Will call the provided EventAction_Destruction method. Not if objRef is faulty.
- * @param objRef: A pointer to the ICustomBody representing a physical object.
- ********************************************************/
- virtual void DestroyObject( const ICustomBody* objRef ) = 0;
+ virtual void UpdateWorld() = 0;
- /********************************************************
- * TODO: @todo doc
- ********************************************************/
- virtual void AddGravity( const API::Gravity &g ) = 0;
- /********************************************************
- * TODO: @todo doc
- ********************************************************/
- virtual void RemoveGravity( const API::Gravity &g ) = 0;
/********************************************************
* Applies an effect to objects that collide with the set volume.
@@ -146,88 +97,6 @@ namespace Oyster
********************************************************/
virtual void ApplyEffect( const Oyster::Collision3D::ICollideable& collideable, void* args, void(hitAction)(ICustomBody*, void*) ) = 0;
- ///********************************************************
- // * Apply force on an object.
- // * @param objRef: A pointer to the ICustomBody representing a physical object.
- // * @param worldPos: Relative to the world origo. (Not relative to object) [m]
- // * @param worldF: Vector with the direction and magnitude of the force. [N]
- // ********************************************************/
- //virtual void ApplyForceAt( const ICustomBody* objRef, const ::Oyster::Math::Float3 &worldPos, const ::Oyster::Math::Float3 &worldF ) = 0;
-
- ///********************************************************
- // * Sets the MomentOfInertia tensor matrix of an object without changing it's angular velocity.
- // * Noticeable effect: The angular momentum will change. Changing the amount of kinetic energy.
- // * @param objRef: A pointer to the ICustomBody representing a physical object.
- // * @param localI: The tensor matrix relative to the axises of the object. @see MomentOfInertia namespace.
- // ********************************************************/
- //virtual void SetMomentOfInertiaTensor_KeepVelocity( const ICustomBody* objRef, const ::Oyster::Math::Float4x4 &localI ) = 0;
- //
- ///********************************************************
- // * Sets the MomentOfInertia tensor matrix of an object without changing it's angular momentum.
- // * Noticeable effect: The angular velocity will change. Can be used to create slow effects.
- // * @param objRef: A pointer to the ICustomBody representing a physical object.
- // * @param localI: The tensor matrix relative to the axises of the object. @see MomentOfInertia namespace.
- // ********************************************************/
- //virtual void SetMomentOfInertiaTensor_KeepMomentum( const ICustomBody* objRef, const ::Oyster::Math::Float4x4 &localI ) = 0;
- //
- ///********************************************************
- // * Sets the mass of an object without changing it's linear velocity.
- // * Noticeable effect: The linear momentum will change. Changing the amount of kinetic energy.
- // * @param objRef: A pointer to the ICustomBody representing a physical object.
- // * @param m: [kg]
- // ********************************************************/
- //virtual void SetMass_KeepVelocity( const ICustomBody* objRef, ::Oyster::Math::Float m ) = 0;
- //
- ///********************************************************
- // * Sets the mass of an object without changing it's linear velocity.
- // * Noticeable effect: The linear velocity will change. Can be used to create slow effects.
- // * @param objRef: A pointer to the ICustomBody representing a physical object.
- // * @param m: [kg]
- // ********************************************************/
- //virtual void SetMass_KeepMomentum( const ICustomBody* objRef, ::Oyster::Math::Float m ) = 0;
- //
- ///********************************************************
- // * Instantly moves an object.
- // * @param objRef: A pointer to the ICustomBody representing a physical object.
- // * @param worldPos: Relative to the world origo. (Not relative to object) [m]
- // ********************************************************/
- //virtual void SetCenter( const ICustomBody* objRef, const ::Oyster::Math::Float3 &worldPos ) = 0;
- //
- ///********************************************************
- // * Instantly redirects object.
- // * @param objRef: A pointer to the ICustomBody representing a physical object.
- // * @param rotation: New rotation.
- // ********************************************************/
- //virtual void SetRotation( const ICustomBody* objRef, const ::Oyster::Math::Float4x4 &rotation ) = 0;
- //
- ///********************************************************
- // * Instantly moves and redirects object.
- // * @param objRef: A pointer to the ICustomBody representing a physical object.
- // * @param orientation: New orientation.
- // ********************************************************/
- //virtual void SetOrientation( const ICustomBody* objRef, const ::Oyster::Math::Float4x4 &orientation ) = 0;
- //
- ///********************************************************
- // * Resizes the boundingBox.
- // * @param objRef: A pointer to the ICustomBody representing a physical object.
- // * @param size: New size of this [m]
- // ********************************************************/
- //virtual void SetSize( const ICustomBody* objRef, const ::Oyster::Math::Float3 &size ) = 0;
-
- /********************************************************
- * Creates a new dynamically allocated object that can be used as a component for more complex ICustomBodies.
- * @param desc: @see API::SimpleBodyDescription
- * @return A pointer along with the responsibility to delete.
- ********************************************************/
- virtual ::Utility::DynamicMemory::UniquePointer CreateRigidBody( const SimpleBodyDescription &desc ) const = 0;
-
- /********************************************************
- * Creates a new dynamically allocated object that can be used as a component for more complex ICustomBodies.
- * @param desc: @see API::SphericalBodyDescription
- * @return A pointer along with the responsibility to delete.
- ********************************************************/
- virtual ::Utility::DynamicMemory::UniquePointer CreateRigidBody( const SphericalBodyDescription &desc ) const = 0;
-
protected:
virtual ~API() {}
};
@@ -246,190 +115,37 @@ namespace Oyster
SubscriptMessage_player_collision_response
};
+
typedef SubscriptMessage (*EventAction_BeforeCollisionResponse)( const ICustomBody *proto, const ICustomBody *deuter );
typedef void (*EventAction_AfterCollisionResponse)( const ICustomBody *proto, const ICustomBody *deuter, ::Oyster::Math::Float kineticEnergyLoss );
typedef void (*EventAction_Move)( const ICustomBody *object );
- typedef Struct::SimpleBodyDescription SimpleBodyDescription;
- typedef Struct::SphericalBodyDescription SphericalBodyDescription;
typedef Struct::CustomBodyState State;
virtual ~ICustomBody() {};
- /********************************************************
- * Creates a complete copy of the current (type)object.
- * @return An ICustomBody pointer along with the responsibility to delete.
- ********************************************************/
- virtual ::Utility::DynamicMemory::UniquePointer Clone() const = 0;
-
- /********************************************************
- * @todo TODO: need doc
- ********************************************************/
- virtual SubscriptMessage CallSubscription_BeforeCollisionResponse( const ICustomBody *deuter ) = 0;
-
- /********************************************************
- * @todo TODO: need doc
- ********************************************************/
- virtual void CallSubscription_AfterCollisionResponse( const ICustomBody *deuter, ::Oyster::Math::Float kineticEnergyLoss ) = 0;
-
- /********************************************************
- * @todo TODO: need doc
- ********************************************************/
- virtual void CallSubscription_Move() = 0;
-
- /********************************************************
- * @todo TODO: need doc
- ********************************************************/
virtual State GetState() const = 0;
-
- /********************************************************
- * @todo TODO: need doc
- ********************************************************/
virtual State & GetState( State &targetMem ) const = 0;
-
- /********************************************************
- * @return the linear velocity of the rigid body in a vector.
- ********************************************************/
- //virtual Math::Float3 GetRigidLinearVelocity() const = 0;
-
- /********************************************************
- * @todo TODO: need doc
- ********************************************************/
virtual void SetState( const State &state ) = 0;
- /********************************************************
- * @return true if Engine should apply gravity on this object.
- ********************************************************/
- virtual bool IsAffectedByGravity() const = 0;
+ virtual void SetSubscription(EventAction_AfterCollisionResponse function) = 0;
+ virtual void SetSubscription(EventAction_Move function) = 0;
- /********************************************************
- * param shape: Any defined sample shape.
- * @return true if this truly intersects with shape.
- ********************************************************/
- virtual bool Intersects( const ::Oyster::Collision3D::ICollideable &shape ) const = 0;
+ virtual void SetLinearVelocity(::Oyster::Math::Float3 velocity) = 0;
+ virtual void SetPosition(::Oyster::Math::Float3 position) = 0;
+ virtual void SetRotation(::Oyster::Math::Float4 quaternion) = 0;
+ virtual void SetRotation(::Oyster::Math::Quaternion quaternion) = 0;
+ virtual void SetRotation(::Oyster::Math::Float3 eulerAngles) = 0;
- /********************************************************
- * Performs a detailed Intersect test and returns if, when and where.
- * @param shape: Any defined sample shape.
- * @param worldPointOfContact: Where at timeOfContact, this and object touches eachother.
- * @return true if this truly intersects with object.
- ********************************************************/
- virtual bool Intersects( const ::Oyster::Collision3D::ICollideable &shape, ::Oyster::Math::Float4 &worldPointOfContact ) const = 0;
-
- /********************************************************
- * Performs a detailed Intersect test and returns if, when and where.
- * @param object: What this is intersect testing against.
- * @param worldPointOfContact: Where at timeOfContact, this and object touches eachother.
- * @return true if this truly intersects with object.
- ********************************************************/
- virtual bool Intersects( const ICustomBody &object, ::Oyster::Math::Float4 &worldPointOfContact ) const = 0;
-
- /********************************************************
- * Sets how far back it needs to be interpolated to not be overlapping worldPointOfContact.
- ********************************************************/
- virtual void SetTimeOfContact( ::Oyster::Math::Float4 &worldPointOfContact ) = 0;
-
- /********************************************************
- * Required by Engine's Collision Search.
- * @param targetMem: Provided memory that written into and then returned.
- * @return a sphere shape that contains the ICustomBody.
- ********************************************************/
- virtual ::Oyster::Collision3D::Sphere & GetBoundingSphere( ::Oyster::Collision3D::Sphere &targetMem = ::Oyster::Collision3D::Sphere() ) const = 0;
-
- /********************************************************
- * Required by Engine's Collision Responsing.
- * @param worldPos: Should be worldPointOfContact from Intersects( ... )
- * @param targetMem: Provided memory that written into and then returned.
- * @return a surface normal in worldSpace.
- ********************************************************/
- virtual ::Oyster::Math::Float4 & GetNormalAt( const ::Oyster::Math::Float4 &worldPos, ::Oyster::Math::Float4 &targetMem = ::Oyster::Math::Float4() ) const = 0;
-
- /********************************************************
- * The gravity normal will have same direction as the total gravity force pulling on this and have the magnitude of 1.0f.
- * @param targetMem: Provided memory that written into and then returned.
- * @return a normalized vector in worldSpace. Exception: Null vector if no gravity been applied.
- ********************************************************/
- virtual ::Oyster::Math::Float3 & GetGravityNormal( ::Oyster::Math::Float3 &targetMem = ::Oyster::Math::Float3() ) const = 0;
+ ::Oyster::Math::Float4x4 GetRotation() const;
+ ::Oyster::Math::Float4x4 GetOrientation() const;
+ ::Oyster::Math::Float4x4 GetView() const;
+ ::Oyster::Math::Float4x4 GetView( const ::Oyster::Math::Float3 &offset ) const;
/********************************************************
* @return the void pointer set by SetCustomTag.
* nullptr if none is set.
********************************************************/
- virtual void * GetCustomTag() const = 0;
-
- ///********************************************************
- // * The world position of this center of gravity.
- // * @param targetMem: Provided memory that written into and then returned.
- // * @return a position in worldSpace.
- // ********************************************************/
- //virtual ::Oyster::Math::Float3 & GetCenter( ::Oyster::Math::Float3 &targetMem = ::Oyster::Math::Float3() ) const = 0;
- //
- ///********************************************************
- // * @param targetMem: Provided memory that written into and then returned.
- // * @return a copy of this's rotation matrix.
- // ********************************************************/
- //virtual ::Oyster::Math::Float4x4 & GetRotation( ::Oyster::Math::Float4x4 &targetMem = ::Oyster::Math::Float4x4() ) const = 0;
- //
- ///********************************************************
- // * @param targetMem: Provided memory that written into and then returned.
- // * @return a copy of this's orientation matrix.
- // ********************************************************/
- //virtual ::Oyster::Math::Float4x4 & GetOrientation( ::Oyster::Math::Float4x4 &targetMem = ::Oyster::Math::Float4x4() ) const = 0;
- //
- ///********************************************************
- // * @param targetMem: Provided memory that written into and then returned.
- // * @return a copy of this's view matrix.
- // ********************************************************/
- //virtual ::Oyster::Math::Float4x4 & GetView( ::Oyster::Math::Float4x4 &targetMem = ::Oyster::Math::Float4x4() ) const = 0;
-
- /********************************************************
- * To not be called if is in Engine
- * Is called during API::Update
- ********************************************************/
- virtual UpdateState Update( ::Oyster::Math::Float timeStepLength ) = 0;
-
- /********************************************************
- * @todo TODO: add doc
- ********************************************************/
- virtual void Predict( ::Oyster::Math::Float4 &outDeltaPos, ::Oyster::Math::Float4 &outDeltaAxis, const ::Oyster::Math::Float4 &actingLinearImpulse, const ::Oyster::Math::Float4 &actingAngularImpulse, ::Oyster::Math::Float deltaTime ) = 0;
-
- /********************************************************
- * Sets which scene this ICustomBody is within.
- * Reserved to only be used by the scene.
- * @todo TODO: create an IScene interface
- ********************************************************/
- virtual void SetScene( void *scene ) = 0;
-
- /********************************************************
- * Sets the function that will be called by the engine
- * whenever a collision occurs.
- * @param functionPointer: If NULL, an empty default function will be set.
- ********************************************************/
- virtual void SetSubscription( EventAction_BeforeCollisionResponse functionPointer ) = 0;
-
- /********************************************************
- * Sets the function that will be called by the engine
- * whenever a collision has finished.
- * @param functionPointer: If NULL, an empty default function will be set.
- ********************************************************/
- virtual void SetSubscription( EventAction_AfterCollisionResponse functionPointer ) = 0;
-
- /********************************************************
- * Sets the function that will be called by the engine
- * whenever an object have moved.
- * @param functionPointer: If NULL, an empty default function will be set.
- ********************************************************/
- virtual void SetSubscription( EventAction_Move functionPointer ) = 0;
-
- /********************************************************
- * @param ignore: True if Engine should not apply Gravity.
- ********************************************************/
- virtual void SetGravity( bool ignore) = 0;
-
- /********************************************************
- * Used by Engine
- * @param normalizedVector: Should have same direction as the pullinggravity.
- ********************************************************/
- virtual void SetGravityNormal( const ::Oyster::Math::Float3 &normalizedVector ) = 0;
+ virtual void* GetCustomTag() const = 0;
/********************************************************
* Not used by the engine itself. Just a quality of life feature
@@ -437,60 +153,6 @@ namespace Oyster
* @param ref: Anything castable to a void pointer, the engine won't care.
********************************************************/
virtual void SetCustomTag( void *ref ) = 0;
-
- ///********************************************************
- // * To not be called if is in Engine
- // * Use API::SetMomentOfInertiaTensor_KeepVelocity(...) instead
- // ********************************************************/
- //virtual void SetMomentOfInertiaTensor_KeepVelocity( const ::Oyster::Math::Float4x4 &localI ) = 0;
- //
- ///********************************************************
- // * To not be called if is in Engine
- // * Use API::SetMomentOfInertiaTensor_KeepMomentum(...)
- // ********************************************************/
- //virtual void SetMomentOfInertiaTensor_KeepMomentum( const ::Oyster::Math::Float4x4 &localI ) = 0;
- //
- ///********************************************************
- // * To not be called if is in Engine
- // * Use API::SetMass_KeepVelocity(...)
- // ********************************************************/
- //virtual void SetMass_KeepVelocity( ::Oyster::Math::Float m ) = 0;
- //
- ///********************************************************
- // * To not be called if is in Engine
- // * Use API::SetMass_KeepMomentum(...)
- // ********************************************************/
- //virtual void SetMass_KeepMomentum( ::Oyster::Math::Float m ) = 0;
- //
- ///********************************************************
- // * To not be called if is in Engine
- // * Use API::SetCenter(...)
- // ********************************************************/
- //virtual void SetCenter( const ::Oyster::Math::Float3 &worldPos ) = 0;
- //
- ///********************************************************
- // * To not be called if is in Engine
- // * Use API::SetRotation(...)
- // ********************************************************/
- //virtual void SetRotation( const ::Oyster::Math::Float4x4 &rotation ) = 0;
- //
- ///********************************************************
- // * To not be called if is in Engine
- // * Use API::SetOrientation(...)
- // ********************************************************/
- //virtual void SetOrientation( const ::Oyster::Math::Float4x4 &orientation ) = 0;
-
- ///********************************************************
- // * To not be called if is in Engine
- // * Use API::SetSize(...)
- // ********************************************************/
- //virtual void SetSize( const ::Oyster::Math::Float3 &size ) = 0;
-
- ///********************************************************
- // * To not be called if is in Engine
- // * Use API::?? @todo TODO:
- // ********************************************************/
- //virtual void SetMomentum( const ::Oyster::Math::Float3 &worldG ) = 0;
};
}
}
diff --git a/Code/GamePhysics/PhysicsStructs-Impl.h b/Code/GamePhysics/PhysicsStructs-Impl.h
index eae72623..07ba0bb2 100644
--- a/Code/GamePhysics/PhysicsStructs-Impl.h
+++ b/Code/GamePhysics/PhysicsStructs-Impl.h
@@ -10,53 +10,14 @@ namespace Oyster
{
namespace Struct
{
- inline SimpleBodyDescription::SimpleBodyDescription()
- {
- this->rotation = ::Oyster::Math::Float3::null;
- this->centerPosition = ::Oyster::Math::Float3::null;
- this->size = ::Oyster::Math::Float3( 1.0f );
- this->mass = 6.0f;
- this->restitutionCoeff = 1.0f;
- this->frictionCoeff_Dynamic = 0.5f;
- this->frictionCoeff_Static = 0.5f;
- this->inertiaTensor = ::Oyster::Physics3D::MomentOfInertia();
- this->subscription_onCollision = NULL;
- this->subscription_onCollisionResponse = NULL;
- this->subscription_onMovement = NULL;
- this->ignoreGravity = false;
- }
-
- inline SphericalBodyDescription::SphericalBodyDescription()
- {
- this->rotation = ::Oyster::Math::Float3::null;
- this->centerPosition = ::Oyster::Math::Float3::null;
- this->radius = 0.5f;
- this->mass = 10.0f;
- this->restitutionCoeff = 1.0f;
- this->frictionCoeff_Dynamic = 0.5f;
- this->frictionCoeff_Static = 0.5f;
- this->subscription_onCollision = NULL;
- this->subscription_onCollisionResponse = NULL;
- this->subscription_onMovement = NULL;
- this->ignoreGravity = false;
- }
-
- inline CustomBodyState::CustomBodyState( ::Oyster::Math::Float mass, ::Oyster::Math::Float restitutionCoeff, ::Oyster::Math::Float staticFrictionCoeff, ::Oyster::Math::Float kineticFrictionCoeff, const ::Oyster::Physics3D::MomentOfInertia &inertiaTensor, const ::Oyster::Math::Float3 &reach, const ::Oyster::Math::Float3 ¢erPos, const ::Oyster::Math::Float3 &rotation, const ::Oyster::Math::Float3 &linearMomentum, const ::Oyster::Math::Float3 &angularMomentum, const ::Oyster::Math::Float3 &gravityNormal )
+ inline CustomBodyState::CustomBodyState( ::Oyster::Math::Float mass, ::Oyster::Math::Float restitutionCoeff, ::Oyster::Math::Float staticFrictionCoeff, ::Oyster::Math::Float dynamicFrictionCoeff, const ::Oyster::Math::Float3 ¢erPos, const ::Oyster::Math::Quaternion& quaternion)
{
this->mass = mass;
this->restitutionCoeff = restitutionCoeff;
this->staticFrictionCoeff = staticFrictionCoeff;
- this->kineticFrictionCoeff = kineticFrictionCoeff;
- this->inertiaTensor = inertiaTensor;
- this->reach = reach;
+ this->dynamicFrictionCoeff = dynamicFrictionCoeff;
this->centerPos = centerPos;
- this->angularAxis = rotation;
- this->linearMomentum = linearMomentum;
- this->angularMomentum = angularMomentum;
- this->linearImpulse = this->angularImpulse = ::Oyster::Math::Float3::null;
- this->deltaPos = this->deltaAxis = ::Oyster::Math::Float3::null;
- this->isSpatiallyAltered = this->isDisturbed = this->isForwarded = false;
- this->gravityNormal = gravityNormal;
+ this->quaternion = quaternion;
}
inline CustomBodyState & CustomBodyState::operator = ( const CustomBodyState &state )
@@ -64,489 +25,34 @@ namespace Oyster
this->mass = state.mass;
this->restitutionCoeff = state.restitutionCoeff;
this->staticFrictionCoeff = state.staticFrictionCoeff;
- this->kineticFrictionCoeff = state.kineticFrictionCoeff;
- this->inertiaTensor = state.inertiaTensor;
- this->reach = state.reach;
+ this->dynamicFrictionCoeff = state.dynamicFrictionCoeff;
this->centerPos = state.centerPos;
- this->angularAxis = state.angularAxis;
- this->linearMomentum = state.linearMomentum;
- this->angularMomentum = state.angularMomentum;
- this->linearImpulse = state.linearImpulse;
- this->angularImpulse = state.angularImpulse;
- this->deltaPos = state.deltaPos;
- this->deltaAxis = state.deltaAxis;
- this->isSpatiallyAltered = state.isSpatiallyAltered;
- this->isDisturbed = state.isDisturbed;
- this->isForwarded = state.isForwarded;
- this->gravityNormal = state.gravityNormal;
+ this->quaternion = state.quaternion;
+
return *this;
}
- inline const ::Oyster::Math::Float CustomBodyState::GetMass() const
- {
- return this->mass;
- }
-
- inline const ::Oyster::Math::Float CustomBodyState::GetRestitutionCoeff() const
- {
- return this->restitutionCoeff;
- }
-
- inline const ::Oyster::Math::Float CustomBodyState::GetFrictionCoeff_Static() const
- {
- return this->staticFrictionCoeff;
- }
-
- inline const ::Oyster::Math::Float CustomBodyState::GetFrictionCoeff_Kinetic() const
- {
- return this->kineticFrictionCoeff;
- }
-
- inline const ::Oyster::Physics3D::MomentOfInertia & CustomBodyState::GetMomentOfInertia() const
- {
- return this->inertiaTensor;
- }
-
- inline const ::Oyster::Math::Float3 & CustomBodyState::GetReach() const
- {
- return this->reach;
- }
-
- inline ::Oyster::Math::Float3 CustomBodyState::GetSize() const
- {
- return 2.0f * this->GetReach();
- }
-
- inline const ::Oyster::Math::Float3 & CustomBodyState::GetCenterPosition() const
- {
- return this->centerPos;
- }
-
- inline const ::Oyster::Math::Float3 & CustomBodyState::GetAngularAxis() const
- {
- return this->angularAxis;
- }
inline ::Oyster::Math::Float4x4 CustomBodyState::GetRotation() const
{
- return ::Oyster::Math3D::RotationMatrix( this->GetAngularAxis() );
+ return ::Oyster::Math3D::RotationMatrix( this->quaternion );
}
inline ::Oyster::Math::Float4x4 CustomBodyState::GetOrientation() const
{
- return ::Oyster::Math3D::OrientationMatrix( this->angularAxis, this->centerPos );
- }
-
- inline ::Oyster::Math::Float4x4 CustomBodyState::GetOrientation( const ::Oyster::Math::Float3 &offset ) const
- {
- return ::Oyster::Math3D::OrientationMatrix( this->angularAxis, (this->centerPos + offset) );
+ return ::Oyster::Math3D::OrientationMatrix( this->quaternion, this->centerPos );
}
inline ::Oyster::Math::Float4x4 CustomBodyState::GetView() const
{
- return ::Oyster::Math3D::ViewMatrix( this->angularAxis, this->centerPos );
+ return ::Oyster::Math3D::ViewMatrix( this->quaternion, this->centerPos );
}
inline ::Oyster::Math::Float4x4 CustomBodyState::GetView( const ::Oyster::Math::Float3 &offset ) const
{
- return ::Oyster::Math3D::ViewMatrix( this->angularAxis, (this->centerPos + offset) );
+ return ::Oyster::Math3D::ViewMatrix( this->quaternion, (this->centerPos + offset) );
}
- inline const ::Oyster::Math::Float3 & CustomBodyState::GetLinearMomentum() const
- {
- return this->linearMomentum;
- }
-
- inline ::Oyster::Math::Float3 CustomBodyState::GetLinearMomentum( const ::Oyster::Math::Float3 &at ) const
- {
- ::Oyster::Math::Float3 offset = at - this->centerPos;
- if( offset.Dot(offset) > 0.0f )
- {
- return this->linearMomentum + ::Oyster::Physics3D::Formula::TangentialLinearMomentum( this->angularMomentum, offset );
- }
- return this->linearMomentum;
- }
-
- inline const ::Oyster::Math::Float3 & CustomBodyState::GetAngularMomentum() const
- {
- return this->angularMomentum;
- }
-
- inline const ::Oyster::Math::Float3 & CustomBodyState::GetLinearImpulse() const
- {
- return this->linearImpulse;
- }
-
- inline const ::Oyster::Math::Float3 & CustomBodyState::GetAngularImpulse() const
- {
- return this->angularImpulse;
- }
-
- inline const ::Oyster::Math::Float3 & CustomBodyState::GetForward_DeltaPos() const
- {
- return this->deltaPos;
- }
-
- inline const ::Oyster::Math::Float3 & CustomBodyState::GetForward_DeltaAxis() const
- {
- return this->deltaAxis;
- }
-
- inline const ::Oyster::Math::Float3 & CustomBodyState::GetGravityNormal() const
- {
- return this->gravityNormal;
- }
-
- inline void CustomBodyState::SetMass_KeepMomentum( ::Oyster::Math::Float m )
- {
- this->mass = m;
- }
-
- inline void CustomBodyState::SetMass_KeepVelocity( ::Oyster::Math::Float m )
- {
- if( m != 0.0f )
- { // sanity block!
- this->linearMomentum *= (m / this->mass);
- this->mass = m;
- }
- }
-
- inline void CustomBodyState::SetRestitutionCoeff( ::Oyster::Math::Float e )
- {
- this->restitutionCoeff = e;
- }
-
- inline void CustomBodyState::SetFrictionCoeff( ::Oyster::Math::Float staticU, ::Oyster::Math::Float kineticU )
- {
- this->staticFrictionCoeff = staticU;
- this->kineticFrictionCoeff = kineticU;
- }
-
- inline void CustomBodyState::SetMomentOfInertia_KeepMomentum( const ::Oyster::Physics3D::MomentOfInertia &tensor )
- {
- this->inertiaTensor = tensor;
- }
-
- inline void CustomBodyState::SetMomentOfInertia_KeepVelocity( const ::Oyster::Physics3D::MomentOfInertia &tensor )
- {
- ::Oyster::Math::Quaternion rotation = ::Oyster::Math3D::Rotation(this->angularAxis);
- ::Oyster::Math::Float3 w = this->inertiaTensor.CalculateAngularVelocity( rotation, this->angularMomentum );
- this->inertiaTensor = tensor;
- this->angularMomentum = this->inertiaTensor.CalculateAngularMomentum( rotation, w );
- }
-
- inline void CustomBodyState::SetSize( const ::Oyster::Math::Float3 &size )
- {
- this->SetReach( 0.5f * size );
- }
-
- inline void CustomBodyState::SetReach( const ::Oyster::Math::Float3 &halfSize )
- {
- this->reach = halfSize;
- this->reach = ::Utility::Value::Max( this->reach, ::Oyster::Math::Float3::null );
- this->isSpatiallyAltered = this->isDisturbed = true;
- }
-
- inline void CustomBodyState::SetCenterPosition( const ::Oyster::Math::Float3 ¢erPos )
- {
- this->centerPos = centerPos;
- this->isSpatiallyAltered = this->isDisturbed = true;
- }
-
- inline void CustomBodyState::SetRotation( const ::Oyster::Math::Float3 &angularAxis )
- {
- this->angularAxis = angularAxis;
- this->isSpatiallyAltered = this->isDisturbed = true;
- }
-
- inline void CustomBodyState::SetOrientation( const ::Oyster::Math::Float3 &angularAxis, const ::Oyster::Math::Float3 &translation )
- {
- this->angularAxis = angularAxis ;
- this->centerPos = translation;
- this->isSpatiallyAltered = this->isDisturbed = true;
- }
-
- inline void CustomBodyState::SetLinearMomentum( const ::Oyster::Math::Float3 &g )
- {
- this->linearMomentum = g;
- this->isDisturbed = true;
- }
-
- inline void CustomBodyState::SetAngularMomentum( const ::Oyster::Math::Float3 &h )
- {
- this->angularMomentum = h;
- this->isDisturbed = true;
- }
-
- inline void CustomBodyState::SetLinearImpulse( const ::Oyster::Math::Float3 &j )
- {
- this->linearImpulse = j;
- this->isDisturbed = true;
- }
-
- inline void CustomBodyState::SetAngularImpulse( const ::Oyster::Math::Float3 &j )
- {
- this->angularImpulse = j;
- this->isDisturbed = true;
- }
-
- inline void CustomBodyState::SetGravityNormal( const ::Oyster::Math::Float3 &gravityNormal )
- {
- this->gravityNormal = gravityNormal;
- }
-
- inline void CustomBodyState::AddRotation( const ::Oyster::Math::Float3 &angularAxis )
- {
- this->angularAxis += angularAxis;
- this->isSpatiallyAltered = this->isDisturbed = true;
- }
-
- inline void CustomBodyState::AddTranslation( const ::Oyster::Math::Float3 &deltaPos )
- {
- this->centerPos += deltaPos;
- this->isSpatiallyAltered = this->isDisturbed = true;
- }
-
- inline void CustomBodyState::ApplyLinearImpulse( const ::Oyster::Math::Float3 &j )
- {
- this->linearImpulse += j;
- this->isDisturbed = true;
- }
-
- inline void CustomBodyState::ApplyAngularImpulse( const ::Oyster::Math::Float3 &j )
- {
- this->angularImpulse += j;
- this->isDisturbed = true;
- }
-
- inline void CustomBodyState::ApplyImpulse( const ::Oyster::Math::Float3 &j, const ::Oyster::Math::Float3 &at, const ::Oyster::Math::Float3 &normal )
- {
- ::Oyster::Math::Float3 offset = at - this->centerPos;
- if( offset.Dot(offset) > 0.0f )
- {
- ::Oyster::Math::Float3 deltaAngularImpulse = ::Oyster::Physics3D::Formula::AngularMomentum( j, offset );
-
- this->linearImpulse -= ::Oyster::Physics3D::Formula::TangentialLinearMomentum( deltaAngularImpulse, offset );
- this->angularImpulse += deltaAngularImpulse;
- }
- this->linearImpulse += j;
- this->isDisturbed = true;
- }
-
- inline void CustomBodyState::ApplyFriction( const ::Oyster::Math::Float3 &j )
- {
- this->linearImpulse += j;
- this->isDisturbed = true;
- }
-
- inline void CustomBodyState::ApplyForwarding( const ::Oyster::Math::Float3 &deltaPos, const ::Oyster::Math::Float3 &deltaAxis )
- {
- this->deltaPos += deltaPos;
- this->deltaAxis += deltaAxis;
- this->isDisturbed = this->isForwarded = true;
- }
-
- inline bool CustomBodyState::IsSpatiallyAltered() const
- {
- return this->isSpatiallyAltered;
- }
-
- inline bool CustomBodyState::IsDisturbed() const
- {
- return this->isDisturbed;
- }
-
- inline bool CustomBodyState::IsForwarded() const
- {
- return this->isForwarded;
- }
-
- inline GravityWell::GravityWell( )
- {
- this->position = ::Oyster::Math::Float3::null;
- this->mass = 0.0f;
- }
-
- inline GravityWell::GravityWell( const GravityWell &gravityWell )
- {
- this->position = gravityWell.position;
- this->mass = gravityWell.mass;
- }
-
- inline GravityWell & GravityWell::operator = ( const GravityWell &gravityWell )
- {
- this->position = gravityWell.position;
- this->mass = gravityWell.mass;
-
- return *this;
- }
-
- inline bool GravityWell::operator == ( const GravityWell &gravity ) const
- {
- if( this->position == gravity.position )
- if( this->mass == gravity.mass )
- {
- return true;
- }
- return false;
- }
-
- inline bool GravityWell::operator != ( const GravityWell &gravity ) const
- {
- if( this->position == gravity.position )
- if( this->mass == gravity.mass )
- {
- return false;
- }
- return true;
- }
-
- inline GravityDirected::GravityDirected( )
- {
- this->impulse = ::Oyster::Math::Float3::null;
- }
-
- inline GravityDirected::GravityDirected( const GravityDirected &gravityDirected )
- {
- this->impulse = gravityDirected.impulse;
- }
-
- inline GravityDirected & GravityDirected::operator = ( const GravityDirected &gravityDirected )
- {
- this->impulse = gravityDirected.impulse;
-
- return *this;
- }
-
- inline bool GravityDirected::operator == ( const GravityDirected &gravity ) const
- {
- return this->impulse == gravity.impulse;
- }
-
- inline bool GravityDirected::operator != ( const GravityDirected &gravity ) const
- {
- return this->impulse != gravity.impulse;
- }
-
- inline GravityDirectedField::GravityDirectedField( )
- {
- this->normalizedDirection = ::Oyster::Math::Float3::null;
- this->mass = 0.0f;
- this->magnitude = 0.0f;
- }
-
- inline GravityDirectedField::GravityDirectedField( const GravityDirectedField &gravityDirectedField )
- {
- this->normalizedDirection = gravityDirectedField.normalizedDirection;
- this->mass = gravityDirectedField.mass;
- this->magnitude = gravityDirectedField.magnitude;
- }
-
- inline GravityDirectedField & GravityDirectedField::operator = ( const GravityDirectedField &gravityDirectedField )
- {
- this->normalizedDirection = gravityDirectedField.normalizedDirection;
- this->mass = gravityDirectedField.mass;
- this->magnitude = gravityDirectedField.magnitude;
-
- return *this;
- }
-
- inline bool GravityDirectedField::operator == ( const GravityDirectedField &gravity ) const
- {
- if( this->normalizedDirection == gravity.normalizedDirection )
- if( this->mass == gravity.mass )
- if( this->magnitude == gravity.magnitude )
- {
- return true;
- }
- return false;
- }
-
- inline bool GravityDirectedField::operator != ( const GravityDirectedField &gravity ) const
- {
- if( this->normalizedDirection == gravity.normalizedDirection )
- if( this->mass == gravity.mass )
- if( this->magnitude == gravity.magnitude )
- {
- return false;
- }
- return true;
- }
-
- inline Gravity::Gravity()
- {
- this->gravityType = GravityType_Undefined;
- }
-
- inline Gravity::Gravity( const Gravity &gravity )
- {
- this->gravityType = gravity.gravityType;
-
- switch( gravity.gravityType )
- {
- case GravityType_Well:
- this->well = gravity.well;
- break;
- case GravityType_Directed:
- this->directed = gravity.directed;
- break;
- case GravityType_DirectedField:
- this->directedField = gravity.directedField;
- break;
- default: break;
- }
- }
-
- inline Gravity & Gravity::operator = ( const Gravity &gravity )
- {
- this->gravityType = gravity.gravityType;
-
- switch( gravity.gravityType )
- {
- case GravityType_Well:
- this->well = gravity.well;
- break;
- case GravityType_Directed:
- this->directed = gravity.directed;
- break;
- case GravityType_DirectedField:
- this->directedField = gravity.directedField;
- break;
- default: break;
- }
-
- return *this;
- }
-
- inline bool Gravity::operator == ( const Gravity &gravity ) const
- {
- if( this->gravityType == gravity.gravityType )
- {
- switch( this->gravityType )
- {
- case GravityType_Well: return this->well == gravity.well;
- case GravityType_Directed: return this->directed == gravity.directed;
- case GravityType_DirectedField: return this->directedField == gravity.directedField;
- default: return true;
- }
- }
- return false;
- }
-
- inline bool Gravity::operator != ( const Gravity &gravity ) const
- {
- if( this->gravityType == gravity.gravityType )
- {
- switch( this->gravityType )
- {
- case GravityType_Well: return this->well != gravity.well;
- case GravityType_Directed: return this->directed != gravity.directed;
- case GravityType_DirectedField: return this->directedField != gravity.directedField;
- default: return false;
- }
- }
- return true;
- }
}
}
}
diff --git a/Code/GamePhysics/PhysicsStructs.h b/Code/GamePhysics/PhysicsStructs.h
index 6bf39a67..fa6c023c 100644
--- a/Code/GamePhysics/PhysicsStructs.h
+++ b/Code/GamePhysics/PhysicsStructs.h
@@ -5,212 +5,40 @@
#include "PhysicsAPI.h"
#include "Inertia.h"
-namespace Oyster { namespace Physics
-{
- namespace Struct
+namespace Oyster
+{
+ namespace Physics
{
- struct SimpleBodyDescription
+ namespace Struct
{
- ::Oyster::Math::Float3 rotation;
- ::Oyster::Math::Float3 centerPosition;
- ::Oyster::Math::Float3 size;
- ::Oyster::Math::Float mass;
- ::Oyster::Math::Float restitutionCoeff;
- ::Oyster::Math::Float frictionCoeff_Static;
- ::Oyster::Math::Float frictionCoeff_Dynamic;
- ::Oyster::Physics3D::MomentOfInertia inertiaTensor;
- ::Oyster::Physics::ICustomBody::EventAction_BeforeCollisionResponse subscription_onCollision;
- ::Oyster::Physics::ICustomBody::EventAction_AfterCollisionResponse subscription_onCollisionResponse;
- ::Oyster::Physics::ICustomBody::EventAction_Move subscription_onMovement;
- bool ignoreGravity;
+ struct CustomBodyState
+ {
+ public:
+ // Default constructor
+ CustomBodyState( ::Oyster::Math::Float mass = 1.0f,
+ ::Oyster::Math::Float restitutionCoeff = 0.5f,
+ ::Oyster::Math::Float staticFrictionCoeff = 1.0f,
+ ::Oyster::Math::Float dynamicFrictionCoeff = 1.0f,
+ const ::Oyster::Math::Float3 ¢erPos = ::Oyster::Math::Float3::null,
+ const ::Oyster::Math::Quaternion &quaternion = ::Oyster::Math::Quaternion(::Oyster::Math::Float3(0, 0, 0), 1));
- SimpleBodyDescription();
- };
+ // Assignment operator
+ CustomBodyState & operator = ( const CustomBodyState &state );
- struct SphericalBodyDescription
- {
- ::Oyster::Math::Float3 rotation;
- ::Oyster::Math::Float3 centerPosition;
- ::Oyster::Math::Float radius;
- ::Oyster::Math::Float mass;
- ::Oyster::Math::Float restitutionCoeff;
- ::Oyster::Math::Float frictionCoeff_Static;
- ::Oyster::Math::Float frictionCoeff_Dynamic;
- ::Oyster::Physics::ICustomBody::EventAction_BeforeCollisionResponse subscription_onCollision;
- ::Oyster::Physics::ICustomBody::EventAction_AfterCollisionResponse subscription_onCollisionResponse;
- ::Oyster::Physics::ICustomBody::EventAction_Move subscription_onMovement;
- bool ignoreGravity;
-
- SphericalBodyDescription();
- };
-
- struct CustomBodyState
- {
- public:
- CustomBodyState( ::Oyster::Math::Float mass = 1.0f,
- ::Oyster::Math::Float restitutionCoeff = 1.0f,
- ::Oyster::Math::Float staticFrictionCoeff = 1.0f,
- ::Oyster::Math::Float kineticFrictionCoeff = 1.0f,
- const ::Oyster::Physics3D::MomentOfInertia &inertiaTensor = ::Oyster::Physics3D::MomentOfInertia(),
- const ::Oyster::Math::Float3 &reach = ::Oyster::Math::Float3::null,
- const ::Oyster::Math::Float3 ¢erPos = ::Oyster::Math::Float3::null,
- const ::Oyster::Math::Float3 &rotation = ::Oyster::Math::Float3::null,
- const ::Oyster::Math::Float3 &linearMomentum = ::Oyster::Math::Float3::null,
- const ::Oyster::Math::Float3 &angularMomentum = ::Oyster::Math::Float3::null,
- const ::Oyster::Math::Float3 &gravityNormal = ::Oyster::Math::Float3::null);
-
- CustomBodyState & operator = ( const CustomBodyState &state );
-
- const ::Oyster::Math::Float GetMass() const;
- const ::Oyster::Math::Float GetRestitutionCoeff() const;
- const ::Oyster::Math::Float GetFrictionCoeff_Static() const;
- const ::Oyster::Math::Float GetFrictionCoeff_Kinetic() const;
- const ::Oyster::Physics3D::MomentOfInertia & GetMomentOfInertia() const;
- const ::Oyster::Math::Float3 & GetReach() const;
- ::Oyster::Math::Float3 GetSize() const;
- const ::Oyster::Math::Float3 & GetCenterPosition() const;
- const ::Oyster::Math::Float3 & GetAngularAxis() const;
- ::Oyster::Math::Float4x4 GetRotation() const;
- ::Oyster::Math::Float4x4 GetOrientation() const;
- ::Oyster::Math::Float4x4 GetOrientation( const ::Oyster::Math::Float3 &offset ) const;
- ::Oyster::Math::Float4x4 GetView() const;
- ::Oyster::Math::Float4x4 GetView( const ::Oyster::Math::Float3 &offset ) const;
- const ::Oyster::Math::Float3 & GetLinearMomentum() const;
- ::Oyster::Math::Float3 GetLinearMomentum( const ::Oyster::Math::Float3 &at ) const;
- const ::Oyster::Math::Float3 & GetAngularMomentum() const;
- const ::Oyster::Math::Float3 & GetLinearImpulse() const;
- const ::Oyster::Math::Float3 & GetAngularImpulse() const;
- const ::Oyster::Math::Float3 & GetForward_DeltaPos() const;
- const ::Oyster::Math::Float3 & GetForward_DeltaAxis() const;
- const ::Oyster::Math::Float3 & GetGravityNormal() const;
+ // Get functions that calculate matrices that do not exist as variables
+ ::Oyster::Math::Float4x4 GetRotation() const;
+ ::Oyster::Math::Float4x4 GetOrientation() const;
+ ::Oyster::Math::Float4x4 GetView() const;
+ ::Oyster::Math::Float4x4 GetView( const ::Oyster::Math::Float3 &offset ) const;
- void SetMass_KeepMomentum( ::Oyster::Math::Float m );
- void SetMass_KeepVelocity( ::Oyster::Math::Float m );
- void SetRestitutionCoeff( ::Oyster::Math::Float e );
- void SetFrictionCoeff( ::Oyster::Math::Float staticU, ::Oyster::Math::Float kineticU );
- void SetMomentOfInertia_KeepMomentum( const ::Oyster::Physics3D::MomentOfInertia &tensor );
- void SetMomentOfInertia_KeepVelocity( const ::Oyster::Physics3D::MomentOfInertia &tensor );
- void SetSize( const ::Oyster::Math::Float3 &size );
- void SetReach( const ::Oyster::Math::Float3 &halfSize );
- void SetCenterPosition( const ::Oyster::Math::Float3 ¢erPos );
- void SetRotation( const ::Oyster::Math::Float3 &angularAxis );
- //void SetRotation( const ::Oyster::Math::Float4x4 &rotation );
- //void SetOrientation( const ::Oyster::Math::Float4x4 &orientation );
- void SetOrientation( const ::Oyster::Math::Float3 &angularAxis, const ::Oyster::Math::Float3 &translation );
- void SetLinearMomentum( const ::Oyster::Math::Float3 &g );
- void SetAngularMomentum( const ::Oyster::Math::Float3 &h );
- void SetLinearImpulse( const ::Oyster::Math::Float3 &j );
- void SetAngularImpulse( const ::Oyster::Math::Float3 &j );
- void SetGravityNormal( const ::Oyster::Math::Float3 &gravityNormal );
-
- void AddRotation( const ::Oyster::Math::Float3 &angularAxis );
- void AddTranslation( const ::Oyster::Math::Float3 &deltaPos );
-
- void ApplyLinearImpulse( const ::Oyster::Math::Float3 &j );
- void ApplyAngularImpulse( const ::Oyster::Math::Float3 &j );
- void ApplyImpulse( const ::Oyster::Math::Float3 &j, const ::Oyster::Math::Float3 &at, const ::Oyster::Math::Float3 &normal );
- void CustomBodyState::ApplyFriction( const ::Oyster::Math::Float3 &j);
- void ApplyForwarding( const ::Oyster::Math::Float3 &deltaPos, const ::Oyster::Math::Float3 &deltaAxis );
-
- bool IsSpatiallyAltered() const;
- bool IsDisturbed() const;
- bool IsForwarded() const;
-
- ::Oyster::Math::Float3 linearMomentum;
-
- private:
- ::Oyster::Math::Float mass, restitutionCoeff, staticFrictionCoeff, kineticFrictionCoeff;
- ::Oyster::Physics3D::MomentOfInertia inertiaTensor;
- ::Oyster::Math::Float3 reach, centerPos, angularAxis;
- ::Oyster::Math::Float3 angularMomentum;
- ::Oyster::Math::Float3 linearImpulse, angularImpulse;
- ::Oyster::Math::Float3 deltaPos, deltaAxis; // Forwarding data sum
- ::Oyster::Math::Float3 gravityNormal;
-
- bool isSpatiallyAltered, isDisturbed, isForwarded;
- };
-
- /**
- ###############################################################################
- Can't define structs inside structs in a union therefor they are declared here.
- ###############################################################################
- */
- struct GravityWell
- {
- ::Oyster::Math::Float3 position;
- ::Oyster::Math::Float mass;
-
- GravityWell( );
- GravityWell( const GravityWell &gravityWell );
- GravityWell & operator = ( const GravityWell &gravityWell );
-
- bool operator == ( const GravityWell &gravity ) const;
- bool operator != ( const GravityWell &gravity ) const;
- };
-
- struct GravityDirected
- {
- ::Oyster::Math::Float3 impulse;
-
- GravityDirected( );
- GravityDirected( const GravityDirected &gravityDirected );
- GravityDirected & operator = ( const GravityDirected &gravityDirected );
-
- bool operator == ( const GravityDirected &gravity ) const;
- bool operator != ( const GravityDirected &gravity ) const;
- };
-
- struct GravityDirectedField
- {
- ::Oyster::Math::Float3 normalizedDirection;
- ::Oyster::Math::Float mass;
- ::Oyster::Math::Float magnitude;
-
- GravityDirectedField( );
- GravityDirectedField( const GravityDirectedField &gravityDirectedField );
- GravityDirectedField & operator = ( const GravityDirectedField &gravityDirectedField );
-
- bool operator == ( const GravityDirectedField &gravity ) const;
- bool operator != ( const GravityDirectedField &gravity ) const;
- };
-
- struct Gravity
- {
- enum GravityType
- {
- GravityType_Undefined = -1,
- GravityType_Well = 0,
- GravityType_Directed = 1,
- GravityType_DirectedField = 2,
- } gravityType;
-
- union
- {
- struct
- {
- GravityWell well;
- };
-
- struct
- {
- GravityDirected directed;
- };
-
- struct
- {
- GravityDirectedField directedField;
- };
- };
-
- Gravity( );
- Gravity( const Gravity &gravity );
- Gravity & operator = ( const Gravity &gravity );
-
- bool operator == ( const Gravity &gravity ) const;
- bool operator != ( const Gravity &gravity ) const;
- };
- }
-} }
+ // Variables for state
+ ::Oyster::Math::Float mass, restitutionCoeff, staticFrictionCoeff, dynamicFrictionCoeff;
+ ::Oyster::Math::Float3 reach, centerPos;
+ ::Oyster::Math::Quaternion quaternion;
+ };
+ }
+ }
+}
#include "PhysicsStructs-Impl.h"
diff --git a/Code/Misc/DynamicArray.h b/Code/Misc/DynamicArray.h
index 9d7bbc30..b9d87366 100644
--- a/Code/Misc/DynamicArray.h
+++ b/Code/Misc/DynamicArray.h
@@ -30,6 +30,7 @@ namespace Utility
T& PopBack();
T& Pop(unsigned int index);
+ void Remove(T value);
void Remove(unsigned int index);
void Remove(unsigned int first, unsigned int last);
@@ -168,11 +169,25 @@ namespace Utility
return this->data[index];
}
+ template void DynamicArray::Remove(T value)
+ {
+ T* temp = new T[this->capacity - 1];
+
+ for (int i = 0; i < this->size; i++)
+ {
+ if(this->data[i] == value)
+ {
+ Remove(i);
+ break;
+ }
+ }
+ }
+
template void DynamicArray::Remove(unsigned int index)
{
assert(index < (unsigned int) this->size);
- T* temp = new T[this->capacity - 1];
+ T* temp = new T[this->capacity];
for (int i = 0; i < this->size; i++)
{
diff --git a/Code/Misc/EventHandler/EventButton.h b/Code/Misc/EventHandler/EventButton.h
new file mode 100644
index 00000000..64215da2
--- /dev/null
+++ b/Code/Misc/EventHandler/EventButton.h
@@ -0,0 +1,261 @@
+///////////////////////
+// Sam Svensson 2013 //
+///////////////////////
+
+#ifndef MISC_EVENT_BUTTON_H
+#define MISC_EVENT_BUTTON_H
+
+#include "IEventButton.h"
+
+namespace Oyster
+{
+ namespace Event
+ {
+ template
+ struct ButtonEvent
+ {
+ ButtonState state;
+ IEventButton* sender;
+ Owner owner;
+ void* userData;
+ };
+
+ template
+ class EventButton : public IEventButton
+ {
+ protected:
+ //typedef for callback function pointer
+ typedef void (*EventFunc)(Oyster::Event::ButtonEvent& e);
+
+ struct PrivData
+ {
+ PrivData() : ID(currID++){}
+
+ static unsigned int currID;
+ const unsigned int ID;
+
+ ButtonState previousState;
+ Owner owner;
+ EventFunc eventCallback;
+ void* userData;
+ bool enabled;
+ };
+
+
+ PrivData privData;
+
+ private:
+ //Implement this in the inherited classes for collision against that shape.
+ virtual bool Collision(InputClass *input) = 0;
+
+ public:
+ EventButton();
+ EventButton(Owner owner);
+ EventButton(EventFunc func);
+ EventButton(EventFunc func, Owner owner);
+ EventButton(EventFunc func, Owner owner, void* userData);
+ ~EventButton();
+
+ void Update(InputClass *input);
+
+ //Send event to callback function
+ void SendEvent(ButtonState state);
+
+ //Set
+ void SetUserData(void* data);
+ void SetEventFunc(EventFunc func);
+ void SetOwner(Owner owner);
+
+ //Get
+ bool Enabled();
+ unsigned int GetID();
+ //EventFunc GetFunctionPointer();
+ Owner GetOwner();
+
+ bool operator ==(const EventButton& obj);
+
+ };
+
+ template
+ unsigned int EventButton::PrivData::currID = 0;
+
+ template
+ EventButton::EventButton()
+ {
+ this->privData.eventCallback = NULL;
+ this->privData.userData = NULL;
+ this->privData.previousState = ButtonState_None;
+ this->privData.enabled = true;
+ }
+
+ template
+ EventButton::EventButton(Owner owner)
+ {
+ this->privData.owner = owner;
+ this->privData.eventCallback = NULL;
+ this->privData.userData = NULL;
+ this->privData.previousState = ButtonState_None;
+ this->privData.enabled = true;
+ }
+
+ template
+ EventButton::EventButton(EventFunc func)
+ {
+ this->privData.eventCallback = func;
+ this->privData.userData = NULL;
+ this->privData.previousState = ButtonState_None;
+ this->privData.enabled = true;
+ }
+
+ template
+ EventButton::EventButton(EventFunc func, Owner owner)
+ {
+ this->privData.owner = owner;
+ this->privData.eventCallback = func;
+ this->privData.userData = NULL;
+ this->privData.previousState = ButtonState_None;
+ this->privData.enabled = true;
+ }
+
+ template
+ EventButton::EventButton(EventFunc func, Owner owner, void* userData)
+ {
+ this->privData.owner = owner;
+ this->privData.eventCallback = func;
+ this->privData.userData = userData;
+ this->privData.previousState = ButtonState_None;
+ this->privData.enabled = true;
+ }
+
+ template
+ EventButton::~EventButton()
+ {}
+
+ //Checks for collision and
+ template
+ void EventButton::Update(InputClass *input)
+ {
+ if(this->privData.enabled)
+ {
+ ButtonState currentState = ButtonState_None;
+
+ if(Collision(input))
+ {
+ if(input->IsMousePressed())
+ {
+ //Change state when the mouse button is pressed
+ switch(this->privData.previousState)
+ {
+ case ButtonState_None:
+ currentState = ButtonState_Hover;
+ break;
+
+ case ButtonState_Hover:
+ case ButtonState_Released:
+ currentState = ButtonState_Pressed;
+ break;
+
+ case ButtonState_Pressed:
+ case ButtonState_Down:
+ currentState = ButtonState_Down;
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ //Change state when the mouse button is NOT pressed
+ switch(this->privData.previousState)
+ {
+ case ButtonState_None:
+ case ButtonState_Hover:
+ case ButtonState_Released:
+ currentState = ButtonState_Hover;
+ break;
+
+ case ButtonState_Pressed:
+ case ButtonState_Down:
+ currentState = ButtonState_Released;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ //Only call the callback function when the state has changed.
+ if(this->privData.previousState != currentState)
+ SendEvent(currentState);
+
+ this->privData.previousState = currentState;
+ }
+ }
+
+ template
+ void EventButton::SendEvent(ButtonState state)
+ {
+ if(privData.eventCallback != NULL)
+ {
+ Oyster::Event::ButtonEvent event;
+ event.state = state;
+ event.sender = this;
+ event.owner = privData.owner;
+ event.userData = privData.userData;
+ privData.eventCallback(event);
+ }
+ }
+
+ template
+ void EventButton::SetUserData(void* data)
+ {
+ this->privData.userData = data;
+ }
+
+ template
+ void EventButton::SetEventFunc(EventFunc func)
+ {
+ this->privData.EventFunc = EventFunc;
+ }
+
+ template
+ void EventButton::SetOwner(Owner owner)
+ {
+ this->privData.owner = owner;
+ }
+
+ template
+ bool EventButton::Enabled()
+ {
+ return this->privData.enabled;
+ }
+
+ template
+ unsigned int EventButton::GetID()
+ {
+ return this->privData.ID;
+ }
+
+ /* Something is wrong, can't return EventFunc
+ template
+ EventFunc EventButton::GetFunctionPointer()
+ {
+ return this->privData.eventCallback;
+ }*/
+
+ template
+ Owner EventButton::GetOwner()
+ {
+ return this->privData.owner;
+ }
+
+ template
+ bool EventButton::operator ==(const EventButton& obj)
+ {
+ return (this->privData.ID == obj.privData.ID);
+ }
+ }
+}
+
+
+#endif
\ No newline at end of file
diff --git a/Code/Misc/EventHandler/EventButtonCircle.h b/Code/Misc/EventHandler/EventButtonCircle.h
new file mode 100644
index 00000000..3a298acb
--- /dev/null
+++ b/Code/Misc/EventHandler/EventButtonCircle.h
@@ -0,0 +1,64 @@
+//////////////////////////////////////
+// Created by Pontus Fransson 2014 //
+//////////////////////////////////////
+
+#ifndef MISC_EVENT_BUTTON_CIRCLE_H
+#define MISC_EVENT_BUTTON_CIRCLE_H
+
+#include "EventButton.h"
+#include "../../Input/L_inputClass.h"
+
+namespace Oyster
+{
+ namespace Event
+ {
+ template
+ class EventButtonCircle : public EventButton
+ {
+ public:
+ EventButtonCircle()
+ : EventButton(), xPos(0), yPos(0), radius(0)
+ {}
+ EventButtonCircle(Owner owner, float xPos, float yPos, float radius)
+ : EventButton(owner), xPos(xPos), yPos(yPos), radius(radius)
+ {}
+ EventButtonCircle(void (*EventFunc)( Oyster::Event::ButtonEvent& e), float xPos, float yPos, float radius)
+ : EventButton(EventFunc), xPos(xPos), yPos(yPos), radius(radius)
+ {}
+ EventButtonCircle(void (*EventFunc)( Oyster::Event::ButtonEvent& e), Owner owner, float xPos, float yPos, float radius)
+ : EventButton(EventFunc, owner), xPos(xPos), yPos(yPos), radius(radius)
+ {}
+ EventButtonCircle(void (*EventFunc)( Oyster::Event::ButtonEvent& e), Owner owner, void* userData, float xPos, float yPos, float radius)
+ : EventButton(EventFunc, owner, userData), xPos(xPos), yPos(yPos), radius(radius)
+ {}
+ ~EventButtonCircle()
+ {}
+
+ //Circle vs point collision
+ bool Collision(InputClass* inputObject)
+ {
+ //Should come from the InputClass
+ float xMouse = 2, yMouse = 2;
+
+ float xDiff = xMouse - xPos;
+ float yDiff = yMouse - yPos;
+
+ float length = (xDiff * xDiff) + (yDiff * yDiff);
+
+ if(length <= radius*radius)
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ private:
+ float xPos, yPos;
+ float radius;
+
+ };
+ }
+}
+
+#endif
\ No newline at end of file
diff --git a/Code/Misc/EventHandler/EventButtonCollection.cpp b/Code/Misc/EventHandler/EventButtonCollection.cpp
new file mode 100644
index 00000000..6a77c520
--- /dev/null
+++ b/Code/Misc/EventHandler/EventButtonCollection.cpp
@@ -0,0 +1,51 @@
+//////////////////////////////////////
+// Created by Pontus Fransson 2014 //
+//////////////////////////////////////
+
+#include "EventButtonCollection.h"
+
+#include "../../Input/L_inputClass.h"
+
+using namespace Oyster::Event;
+
+EventButtonCollection::EventButtonCollection()
+ : collectionState(EventCollectionState_Enabled)
+{
+}
+
+EventButtonCollection::~EventButtonCollection()
+{
+ int size = buttons.size();
+ for(int i = 0; i < size; i++)
+ {
+ delete buttons[i];
+ buttons[i] = NULL;
+ }
+}
+
+void EventButtonCollection::Update(InputClass* inputObject)
+{
+ if(this->collectionState == EventCollectionState_Enabled)
+ {
+ for(int i = 0; i < (int)buttons.size(); i++)
+ {
+ buttons[i]->Update(inputObject);
+ }
+ }
+}
+
+EventCollectionState EventButtonCollection::GetState() const
+{
+ return collectionState;
+}
+
+void EventButtonCollection::SetState(const EventCollectionState state)
+{
+ collectionState = state;
+}
+
+void EventButtonCollection::Clear()
+{
+ buttons.clear();
+ collectionState = EventCollectionState_Enabled;
+}
\ No newline at end of file
diff --git a/Code/Misc/EventHandler/EventButtonCollection.h b/Code/Misc/EventHandler/EventButtonCollection.h
new file mode 100644
index 00000000..0cc77b42
--- /dev/null
+++ b/Code/Misc/EventHandler/EventButtonCollection.h
@@ -0,0 +1,58 @@
+//////////////////////////////////////
+// Created by Pontus Fransson 2014 //
+//////////////////////////////////////
+
+#ifndef MISC_EVENT_BUTTON_COLLECTION_H
+#define MISC_EVENT_BUTTON_COLLECTION_H
+
+#include "../../Input/L_inputClass.h"
+
+#include "../DynamicArray.h"
+
+#include "IEventButton.h"
+#include "EventButton.h"
+
+#include
+
+namespace Oyster
+{
+ namespace Event
+ {
+ enum EventCollectionState
+ {
+ EventCollectionState_Disabled,
+ EventCollectionState_Enabled,
+
+ EventCollectionState_Count,
+ EventCollectionState_Unknown = -1,
+ };
+
+ class EventButtonCollection
+ {
+ public:
+ EventButtonCollection();
+ ~EventButtonCollection();
+
+ void Update(InputClass* inputObject);
+
+ template
+ void AddButton(EventButton* button)
+ {
+ buttons.push_back(button);
+ }
+
+ EventCollectionState GetState() const;
+ void SetState(const EventCollectionState state);
+
+ //Clear all buttons and reset the state.
+ void Clear();
+
+ private:
+ std::vector buttons;
+ EventCollectionState collectionState;
+
+ };
+ }
+}
+
+#endif
\ No newline at end of file
diff --git a/Code/Misc/EventHandler/EventButtonRectangle.h b/Code/Misc/EventHandler/EventButtonRectangle.h
new file mode 100644
index 00000000..fc917437
--- /dev/null
+++ b/Code/Misc/EventHandler/EventButtonRectangle.h
@@ -0,0 +1,60 @@
+//////////////////////////////////////
+// Created by Pontus Fransson 2014 //
+//////////////////////////////////////
+
+#ifndef MISC_EVENT_BUTTON_RECTANGLE_H
+#define MISC_EVENT_BUTTON_RECTANGLE_H
+
+#include "EventButton.h"
+#include "../../Input/L_inputClass.h"
+
+namespace Oyster
+{
+ namespace Event
+ {
+ template
+ class EventButtonRectangle : public EventButton
+ {
+ public:
+ EventButtonRectangle()
+ : EventButton(), xPos(0), yPos(0), halfWidth(0), halfHeight(0)
+ {}
+ EventButtonRectangle(Owner owner, float xPos, float yPos, float halfWidth, float halfHeight)
+ : EventButton(owner), xPos(xPos), yPos(yPos), halfWidth(halfWidth), halfHeight(halfHeight)
+ {}
+ EventButtonRectangle(void (*EventFunc)( Oyster::Event::ButtonEvent& e), float xPos, float yPos, float halfWidth, float halfHeight)
+ : EventButton(EventFunc), xPos(xPos), yPos(yPos), halfWidth(halfWidth), halfHeight(halfHeight)
+ {}
+ EventButtonRectangle(void (*EventFunc)( Oyster::Event::ButtonEvent& e), Owner owner, float xPos, float yPos, float halfWidth, float halfHeight)
+ : EventButton(EventFunc, owner), xPos(xPos), yPos(yPos), halfWidth(halfWidth), halfHeight(halfHeight)
+ {}
+ EventButtonRectangle(void (*EventFunc)( Oyster::Event::ButtonEvent& e), Owner owner, void* userData, float xPos, float yPos, float halfWidth, float halfHeight)
+ : EventButton(EventFunc, owner, userData), xPos(xPos), yPos(yPos), halfWidth(halfWidth), halfHeight(halfHeight)
+ {}
+ ~EventButtonRectangle()
+ {}
+
+ //Circle vs point collision
+ bool Collision(InputClass* inputObject)
+ {
+ //Should come from the InputClass
+ float xMouse = 1, yMouse = 0;
+
+ if(xMouse >= xPos - halfWidth && xMouse <= xPos + halfWidth
+ && yMouse >= yPos - halfHeight && yMouse <= yPos + halfHeight)
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ private:
+ float xPos, yPos;
+ float halfWidth, halfHeight;
+
+ };
+ }
+}
+
+#endif
\ No newline at end of file
diff --git a/Code/Misc/EventHandler/EventHandler.cpp b/Code/Misc/EventHandler/EventHandler.cpp
new file mode 100644
index 00000000..a7347075
--- /dev/null
+++ b/Code/Misc/EventHandler/EventHandler.cpp
@@ -0,0 +1,47 @@
+//////////////////////////////////////
+// Created by Pontus Fransson 2014 //
+//////////////////////////////////////
+
+#include "EventHandler.h"
+
+using namespace Oyster::Event;
+
+Oyster::Event::EventHandler EvtHandler;
+
+EventHandler& EventHandler::Instance()
+{
+ return EvtHandler;
+}
+
+EventHandler::EventHandler()
+{
+}
+
+EventHandler::~EventHandler()
+{
+ int size = collections.size();
+ for(int i = 0; i < size; i++)
+ {
+ delete collections[i];
+ }
+}
+
+void EventHandler::Update(InputClass* inputObject)
+{
+ for(int i = 0; i < (int)collections.size(); i++)
+ {
+ collections.at(i)->Update(inputObject);
+ }
+}
+
+void EventHandler::AddCollection(EventButtonCollection& collection)
+{
+ collections.push_back(&collection);
+}
+
+EventButtonCollection& EventHandler::CreateCollection()
+{
+ EventButtonCollection* temp = new EventButtonCollection;
+ collections.push_back(temp);
+ return *temp;
+}
\ No newline at end of file
diff --git a/Code/Misc/EventHandler/EventHandler.h b/Code/Misc/EventHandler/EventHandler.h
new file mode 100644
index 00000000..4ca1a9ab
--- /dev/null
+++ b/Code/Misc/EventHandler/EventHandler.h
@@ -0,0 +1,41 @@
+//////////////////////////////////////
+// Created by Pontus Fransson 2014 //
+//////////////////////////////////////
+
+#ifndef MISC_EVENT_HANDLER_H
+#define MISC_EVENT_HANDLER_H
+
+#include "../../Input/L_inputClass.h"
+
+#include "EventButtonCollection.h"
+#include "EventButton.h"
+#include "EventButtonCircle.h"
+#include "EventButtonRectangle.h"
+
+#include
+
+namespace Oyster
+{
+ namespace Event
+ {
+ class EventHandler
+ {
+ public:
+ EventHandler();
+ ~EventHandler();
+
+ static EventHandler& Instance();
+
+ void Update(InputClass* inputObject);
+
+ void AddCollection(EventButtonCollection& collection);
+ EventButtonCollection& CreateCollection();
+
+ private:
+ std::vector collections;
+
+ };
+ }
+}
+
+#endif
\ No newline at end of file
diff --git a/Code/Misc/EventHandler/IEventButton.h b/Code/Misc/EventHandler/IEventButton.h
new file mode 100644
index 00000000..901a8265
--- /dev/null
+++ b/Code/Misc/EventHandler/IEventButton.h
@@ -0,0 +1,41 @@
+//////////////////////////////////////
+// Created by Pontus Fransson 2014 //
+//////////////////////////////////////
+
+#ifndef MISC_IEVENT_BUTTON
+#define MISC_IEVENT_BUTTON
+
+class InputClass;
+
+namespace Oyster
+{
+ namespace Event
+ {
+ enum ButtonState
+ {
+ ButtonState_None,
+ ButtonState_Hover,
+ ButtonState_Pressed,
+ ButtonState_Down,
+ ButtonState_Released,
+ };
+
+ class IEventButton
+ {
+ public:
+ virtual ~IEventButton(){}
+
+ virtual void Update(InputClass *input){}
+
+ virtual void SendEvent(ButtonState state){}
+
+ struct ButtonEvent;
+ virtual void SetEventFunc(void (*EventFunc)( ButtonEvent e )){}
+
+ virtual unsigned int GetID(){ return -1; }
+
+ };
+ }
+}
+
+#endif
\ No newline at end of file
diff --git a/Code/Misc/LinkedList.h b/Code/Misc/LinkedList.h
new file mode 100644
index 00000000..175f043c
--- /dev/null
+++ b/Code/Misc/LinkedList.h
@@ -0,0 +1,225 @@
+/////////////////////////////////////////////////////////////////////
+// Created by [Dennis Andersen] [2013]
+/////////////////////////////////////////////////////////////////////
+#ifndef MISC_LINKED_LIST_H
+#define MISC_LINKED_LIST_H
+
+
+namespace Utility
+{
+ namespace DynamicMemory
+ {
+ template
+ class LinkedList
+ {
+ private:
+ class Node
+ {
+ public:
+ Type data;
+ Node *next;
+ Node() :next(0) { }
+ Node(Type t) :next(0), data(t) { }
+ ~Node() { next = 0; }
+ };
+
+ public:
+ LinkedList();
+ ~LinkedList();
+
+ Type& operator[](int index);
+
+ void PushFront(Type value);
+ Type PopFront();
+ void PushBack(Type value);
+ Type PopBack();
+ Type PeakFront();
+ Type PeakBack();
+
+ void Remove(Type value);
+ bool IsEmpty();
+ int Size();
+ void Clear();
+
+ private:
+ void Destroy(Node* n);
+
+
+
+ private:
+ Node *first;
+ Node *last;
+ int nrOfNodes;
+ };
+
+
+
+ template LinkedList::LinkedList()
+ {
+ this->first = 0;
+ this->last = 0;
+ this->nrOfNodes = 0;
+ }
+ template LinkedList::~LinkedList()
+ {
+ this->last = 0;
+ this->Destroy(this->first);
+ }
+ template Type& LinkedList::operator[](int index)
+ {
+ if(this->index >= this->nrofNodes || index < 0)
+ {
+ throw;
+ }
+ int i = 0;
+ LinkedList::Node* walker = this->first;
+ while (i != index)
+ {
+ walker = walker->next;
+ i++;
+ }
+
+ return walker->data;
+ }
+ template void LinkedList::PushFront(Type value)
+ {
+ Node *n = new Node(value);
+ n->next = this->first;
+ this->first = n;
+
+ if(!this->nrOfNodes)
+ this->back = this->front;
+
+ this->nrOfNodes++;
+ }
+ template Type LinkedList::PopFront()
+ {
+ if(!this->first)
+ {
+ throw;
+ }
+
+ Type temp = this->first->data;
+ Node* head = this->first;
+ this->first = this->first->next;
+ delete head;
+ this->nrOfNodes--;
+ return temp;
+ }
+ template void LinkedList::PushBack(Type value)
+ {
+ Node* n = new Node(value);
+
+ if(!this->first)
+ {
+ this->first = n;
+ this->last = n;
+ }
+ else
+ {
+ this->last->next = n;
+ this->last = n;
+ }
+ this->nrOfNodes++;
+ }
+ template Type LinkedList::PopBack()
+ {
+ if(!this->first)
+ throw;
+
+ Type val = this->last->data;
+ Node* walker = this->first;
+ while (walker)
+ {
+ if(walker->next == this->last)
+ {
+ delete this->last;
+ this->last = walker;
+ walker = 0;
+ this->nrOfNodes--;
+ }
+ }
+ }
+ template Type LinkedList::PeakFront()
+ {
+ if(!this->front)
+ throw;
+ return this->first->data;
+ }
+ template Type LinkedList::PeakBack()
+ {
+ if(!this->last)
+ throw;
+ return this->last->data;
+ }
+ template void LinkedList::Remove(Type value)
+ {
+ Node *w = this->first;
+ if(this->nrOfNodes == 1) //Sepcial case
+ {
+ //First and last is equal
+ if(this->first->data == value)
+ {
+ delete this->first;
+ this->first = 0;
+ this->last = 0;
+ this->nrOfNodes--;
+ }
+ }
+ else
+ {
+ Node *prev = 0;
+ while (w)
+ {
+ if(w->data == value)
+ {
+ if(w == this->first)
+ {
+ this->first = this->first->next;
+ delete w;
+ w = 0;
+ }
+ else if (w == this->last)
+ {
+ this->last = prev;
+ delete w;
+ w = 0;
+ }
+ else
+ {
+ prev->next = w->next;
+ delete w;
+ w = 0;
+ }
+ }
+ else
+ {
+ prev = w;
+ w = w->next;
+ }
+ }
+ }
+ }
+ template bool LinkedList::IsEmpty()
+ {
+ return (this->nrOfNodes == 0);
+ }
+ template int LinkedList::Size()
+ {
+ return this->nrOfNodes;
+ }
+ template void LinkedList::Clear()
+ {
+ this->Destroy(this->first);
+ }
+ template void LinkedList::Destroy(Node* n)
+ {
+ if(n)
+ {
+ Destroy(n->next);
+ delete n;
+ }
+ }
+ }
+}
+#endif // !MISC_LINKED_LIST_H
diff --git a/Code/Misc/Misc.vcxproj b/Code/Misc/Misc.vcxproj
index 512784e7..ef2c7c69 100644
--- a/Code/Misc/Misc.vcxproj
+++ b/Code/Misc/Misc.vcxproj
@@ -146,6 +146,8 @@
+
+
false
@@ -184,8 +186,15 @@
+
+
+
+
+
+
+
diff --git a/Code/Misc/Misc.vcxproj.filters b/Code/Misc/Misc.vcxproj.filters
index 8413642a..65bde701 100644
--- a/Code/Misc/Misc.vcxproj.filters
+++ b/Code/Misc/Misc.vcxproj.filters
@@ -51,6 +51,12 @@
Source Files
+
+ Source Files
+
+
+ Source Files
+
@@ -116,5 +122,26 @@
Header Files
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
\ No newline at end of file
diff --git a/Code/OysterPhysics3D/RigidBody.cpp b/Code/OysterPhysics3D/RigidBody.cpp
index f7a5646e..43d6f9a4 100644
--- a/Code/OysterPhysics3D/RigidBody.cpp
+++ b/Code/OysterPhysics3D/RigidBody.cpp
@@ -13,7 +13,7 @@ using namespace ::Utility::Value;
RigidBody::RigidBody( )
{ // by Dan Andersson
this->centerPos = Float4::standard_unit_w;
- this->axis = Float4::null;
+ this->quaternion = Quaternion(Float3(0, 0, 0), 1);
this->boundingReach = Float4( 0.5f, 0.5f, 0.5f, 0.0f );
this->momentum_Linear = Float4::null;
this->momentum_Angular = Float4::null;
@@ -24,13 +24,12 @@ RigidBody::RigidBody( )
this->frictionCoeff_Kinetic = 1.0f;
this->mass = 10;
this->momentOfInertiaTensor = MomentOfInertia();
- this->rotation = Quaternion::identity;
}
RigidBody & RigidBody::operator = ( const RigidBody &body )
{ // by Dan Andersson
this->centerPos = body.centerPos;
- this->axis = body.axis;
+ this->quaternion = body.quaternion;
this->boundingReach = body.boundingReach;
this->momentum_Linear = body.momentum_Linear;
this->momentum_Angular = body.momentum_Angular;
@@ -41,7 +40,6 @@ RigidBody & RigidBody::operator = ( const RigidBody &body )
this->frictionCoeff_Kinetic = body.frictionCoeff_Kinetic;
this->mass = body.mass;
this->momentOfInertiaTensor = body.momentOfInertiaTensor;
- this->rotation = body.rotation;
return *this;
}
@@ -55,19 +53,14 @@ void RigidBody::Update_LeapFrog( Float updateFrameLength )
this->momentum_Angular = this->momentum_Angular*0.99f;
// ds = dt * Formula::LinearVelocity( m, avg_G ) = dt * avg_G / m = (dt / m) * avg_G
- Float3 delta = AverageWithDelta( this->momentum_Linear, this->impulse_Linear );
- Float3 newPos = ( updateFrameLength)*this->momentum_Linear;
+ Float3 delta = this->momentum_Linear;
+ Float3 newPos = (updateFrameLength)*this->momentum_Linear;
this->centerPos += newPos;
-
- if(this->mass == 70)
- {
- const char *breakpoint = "STOP";
- }
// updating the angular
// dO = dt * Formula::AngularVelocity( (RI)^-1, avg_H ) = dt * (RI)^-1 * avg_H
- this->axis += updateFrameLength * this->momentOfInertiaTensor.CalculateAngularVelocity( this->rotation, AverageWithDelta(this->momentum_Angular, this->impulse_Angular) );
- this->rotation = Rotation( this->axis );
+ /*this->axis += updateFrameLength*this->momentOfInertiaTensor.CalculateAngularVelocity( this->rotation, this->momentum_Angular );
+ this->rotation = Rotation( this->axis );*/
// update momentums and clear impulse_Linear and impulse_Angular
this->momentum_Linear += this->impulse_Linear;
@@ -89,14 +82,14 @@ void RigidBody::Predict_LeapFrog( Float3 &outDeltaPos, Float3 &outDeltaAxis, con
// dO = dt * Formula::AngularVelocity( (RI)^-1, avg_H ) = dt * (RI)^-1 * avg_H
//outDeltaAxis = Formula::AngularVelocity( wMomentOfInertiaTensor.GetInverse(), AverageWithDelta(this->momentum_Angular, actingAngularImpulse) );
- outDeltaAxis = this->momentOfInertiaTensor.CalculateAngularVelocity( this->rotation, AverageWithDelta(this->momentum_Angular, this->impulse_Angular) );
+ //utDeltaAxis = this->momentOfInertiaTensor.CalculateAngularVelocity( this->rotation, AverageWithDelta(this->momentum_Angular, this->impulse_Angular) );
}
void RigidBody::Move( const Float3 &deltaPos, const Float3 &deltaAxis )
{
- this->centerPos += deltaPos;
- this->axis += deltaAxis;
- this->rotation = Rotation( this->axis );
+ //this->centerPos += deltaPos;
+ //this->axis += deltaAxis;
+ //this->rotation = Rotation( this->axis );
}
void RigidBody::ApplyImpulse( const Float3 &worldJ, const Float3 &atWorldPos )
@@ -125,22 +118,22 @@ Float RigidBody::GetMass() const
const Quaternion & RigidBody::GetRotationQuaternion() const
{ // by Dan Andersson
- return this->rotation;
+ return this->quaternion;
}
Float4x4 RigidBody::GetRotationMatrix() const
{ // by Dan Andersson
- return RotationMatrix( this->rotation );
+ return RotationMatrix( quaternion );
}
Float4x4 RigidBody::GetOrientation() const
{ // by Dan Andersson
- return ::Oyster::Math3D::OrientationMatrix( this->rotation, this->centerPos );
+ return ::Oyster::Math3D::OrientationMatrix( this->quaternion, this->centerPos );
}
Float4x4 RigidBody::GetView() const
{ // by Dan Andersson
- return ViewMatrix( this->rotation, this->centerPos );
+ return ViewMatrix( this->quaternion, this->centerPos );
}
Float3 RigidBody::GetVelocity_Linear() const
@@ -150,7 +143,7 @@ Float3 RigidBody::GetVelocity_Linear() const
Float3 RigidBody::GetVelocity_Angular() const
{ // by Dan Andersson
- return this->momentOfInertiaTensor.CalculateAngularVelocity( this->rotation, this->momentum_Angular );
+ return Float3(0, 0, 0);
}
Float3 RigidBody::GetLinearMomentum( const Float3 &atWorldPos ) const
@@ -165,9 +158,7 @@ Float3 RigidBody::GetLinearMomentum( const Float3 &atWorldPos ) const
void RigidBody::SetMomentOfInertia_KeepVelocity( const MomentOfInertia &localTensorI )
{ // by Dan Andersson
- Float3 w = this->momentOfInertiaTensor.CalculateAngularVelocity( this->rotation, this->momentum_Angular );
- this->momentOfInertiaTensor = localTensorI;
- this->momentum_Angular = this->momentOfInertiaTensor.CalculateAngularVelocity( this->rotation, w );
+
}
void RigidBody::SetMomentOfInertia_KeepMomentum( const MomentOfInertia &localTensorI )
@@ -193,10 +184,9 @@ void RigidBody::SetMass_KeepMomentum( const Float &m )
}
}
-void RigidBody::SetRotation( const Float3 &axis )
+void RigidBody::SetRotation( const ::Oyster::Math::Quaternion &quaternion )
{ // by Dan Andersson
- this->axis = axis;
- this->rotation = Rotation( this->axis );
+ this->quaternion = quaternion;
}
void RigidBody::SetMomentum_Linear( const Float3 &worldG, const Float3 &atWorldPos )
@@ -215,12 +205,12 @@ void RigidBody::SetVelocity_Linear( const Float3 &worldV, const Float3 &atWorldP
{ // by Dan Andersson
Float3 worldOffset = atWorldPos - this->centerPos;
this->momentum_Linear = Formula::LinearMomentum( this->mass, VectorProjection(worldV, worldOffset) );
- this->momentum_Angular = this->momentOfInertiaTensor.CalculateAngularMomentum( this->rotation, Formula::AngularVelocity(worldV, worldOffset) );
+ this->momentum_Angular = this->momentOfInertiaTensor.CalculateAngularMomentum( this->quaternion, Formula::AngularVelocity(worldV, worldOffset) );
}
void RigidBody::SetVelocity_Angular( const Float3 &worldW )
{ // by Dan Andersson
- this->momentum_Angular = this->momentOfInertiaTensor.CalculateAngularMomentum( this->rotation, worldW );
+ this->momentum_Angular = this->momentOfInertiaTensor.CalculateAngularMomentum( this->quaternion, worldW );
}
void RigidBody::SetImpulse_Linear( const Float3 &worldJ, const Float3 &atWorldPos )
diff --git a/Code/OysterPhysics3D/RigidBody.h b/Code/OysterPhysics3D/RigidBody.h
index f7aebd22..2d2226cf 100644
--- a/Code/OysterPhysics3D/RigidBody.h
+++ b/Code/OysterPhysics3D/RigidBody.h
@@ -15,8 +15,8 @@ namespace Oyster { namespace Physics3D
struct RigidBody
{ //! A struct of a simple rigid body.
public:
+ ::Oyster::Math::Quaternion quaternion;
::Oyster::Math::Float3 centerPos, //!< Location of the body's center in the world.
- axis, //!< Euler rotationAxis of the body.
boundingReach, //!<
momentum_Linear, //!< The linear momentum G (kg*m/s).
momentum_Angular, //!< The angular momentum H (Nm*s) around an parallell axis.
@@ -64,7 +64,7 @@ namespace Oyster { namespace Physics3D
void SetMass_KeepMomentum( const ::Oyster::Math::Float &m );
//void SetOrientation( const ::Oyster::Math::Float4x4 &o );
- void SetRotation( const ::Oyster::Math::Float3 &axis );
+ void SetRotation( const ::Oyster::Math::Quaternion &quaternion );
void SetSize( const ::Oyster::Math::Float3 &widthHeight );
void SetMomentum_Linear( const ::Oyster::Math::Float3 &worldG, const ::Oyster::Math::Float3 &atWorldPos );
@@ -81,7 +81,7 @@ namespace Oyster { namespace Physics3D
::Oyster::Math::Float mass; //!< m (kg)
//::Oyster::Math::Float4x4 momentOfInertiaTensor; //!< I (Nm*s) Tensor matrix ( only need to be 3x3 matrix, but is 4x4 for future hardware acceleration ) (localValue)
::Oyster::Physics3D::MomentOfInertia momentOfInertiaTensor;
- ::Oyster::Math::Quaternion rotation; //!< RotationAxis of the body.
+ //::Oyster::Math::Quaternion rotation; //!< RotationAxis of the body.
};
} }
diff --git a/Code/Physics/Bullet Source/Bullet-C-Api.h b/Code/Physics/Bullet Source/Bullet-C-Api.h
new file mode 100644
index 00000000..f27a17d5
--- /dev/null
+++ b/Code/Physics/Bullet Source/Bullet-C-Api.h
@@ -0,0 +1,176 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+ Draft high-level generic physics C-API. For low-level access, use the physics SDK native API's.
+ Work in progress, functionality will be added on demand.
+
+ If possible, use the richer Bullet C++ API, by including "btBulletDynamicsCommon.h"
+*/
+
+#ifndef BULLET_C_API_H
+#define BULLET_C_API_H
+
+#define PL_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name
+
+#ifdef BT_USE_DOUBLE_PRECISION
+typedef double plReal;
+#else
+typedef float plReal;
+#endif
+
+typedef plReal plVector3[3];
+typedef plReal plQuaternion[4];
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Particular physics SDK (C-API) */
+ PL_DECLARE_HANDLE(plPhysicsSdkHandle);
+
+/** Dynamics world, belonging to some physics SDK (C-API)*/
+ PL_DECLARE_HANDLE(plDynamicsWorldHandle);
+
+/** Rigid Body that can be part of a Dynamics World (C-API)*/
+ PL_DECLARE_HANDLE(plRigidBodyHandle);
+
+/** Collision Shape/Geometry, property of a Rigid Body (C-API)*/
+ PL_DECLARE_HANDLE(plCollisionShapeHandle);
+
+/** Constraint for Rigid Bodies (C-API)*/
+ PL_DECLARE_HANDLE(plConstraintHandle);
+
+/** Triangle Mesh interface (C-API)*/
+ PL_DECLARE_HANDLE(plMeshInterfaceHandle);
+
+/** Broadphase Scene/Proxy Handles (C-API)*/
+ PL_DECLARE_HANDLE(plCollisionBroadphaseHandle);
+ PL_DECLARE_HANDLE(plBroadphaseProxyHandle);
+ PL_DECLARE_HANDLE(plCollisionWorldHandle);
+
+/**
+ Create and Delete a Physics SDK
+*/
+
+ extern plPhysicsSdkHandle plNewBulletSdk(void); //this could be also another sdk, like ODE, PhysX etc.
+ extern void plDeletePhysicsSdk(plPhysicsSdkHandle physicsSdk);
+
+/** Collision World, not strictly necessary, you can also just create a Dynamics World with Rigid Bodies which internally manages the Collision World with Collision Objects */
+
+ typedef void(*btBroadphaseCallback)(void* clientData, void* object1,void* object2);
+
+ extern plCollisionBroadphaseHandle plCreateSapBroadphase(btBroadphaseCallback beginCallback,btBroadphaseCallback endCallback);
+
+ extern void plDestroyBroadphase(plCollisionBroadphaseHandle bp);
+
+ extern plBroadphaseProxyHandle plCreateProxy(plCollisionBroadphaseHandle bp, void* clientData, plReal minX,plReal minY,plReal minZ, plReal maxX,plReal maxY, plReal maxZ);
+
+ extern void plDestroyProxy(plCollisionBroadphaseHandle bp, plBroadphaseProxyHandle proxyHandle);
+
+ extern void plSetBoundingBox(plBroadphaseProxyHandle proxyHandle, plReal minX,plReal minY,plReal minZ, plReal maxX,plReal maxY, plReal maxZ);
+
+/* todo: add pair cache support with queries like add/remove/find pair */
+
+ extern plCollisionWorldHandle plCreateCollisionWorld(plPhysicsSdkHandle physicsSdk);
+
+/* todo: add/remove objects */
+
+
+/* Dynamics World */
+
+ extern plDynamicsWorldHandle plCreateDynamicsWorld(plPhysicsSdkHandle physicsSdk);
+
+ extern void plDeleteDynamicsWorld(plDynamicsWorldHandle world);
+
+ extern void plStepSimulation(plDynamicsWorldHandle, plReal timeStep);
+
+ extern void plAddRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object);
+
+ extern void plRemoveRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object);
+
+
+/* Rigid Body */
+
+ extern plRigidBodyHandle plCreateRigidBody( void* user_data, float mass, plCollisionShapeHandle cshape );
+
+ extern void plDeleteRigidBody(plRigidBodyHandle body);
+
+
+/* Collision Shape definition */
+
+ extern plCollisionShapeHandle plNewSphereShape(plReal radius);
+ extern plCollisionShapeHandle plNewBoxShape(plReal x, plReal y, plReal z);
+ extern plCollisionShapeHandle plNewCapsuleShape(plReal radius, plReal height);
+ extern plCollisionShapeHandle plNewConeShape(plReal radius, plReal height);
+ extern plCollisionShapeHandle plNewCylinderShape(plReal radius, plReal height);
+ extern plCollisionShapeHandle plNewCompoundShape(void);
+ extern void plAddChildShape(plCollisionShapeHandle compoundShape,plCollisionShapeHandle childShape, plVector3 childPos,plQuaternion childOrn);
+
+ extern void plDeleteShape(plCollisionShapeHandle shape);
+
+ /* Convex Meshes */
+ extern plCollisionShapeHandle plNewConvexHullShape(void);
+ extern void plAddVertex(plCollisionShapeHandle convexHull, plReal x,plReal y,plReal z);
+/* Concave static triangle meshes */
+ extern plMeshInterfaceHandle plNewMeshInterface(void);
+ extern void plAddTriangle(plMeshInterfaceHandle meshHandle, plVector3 v0,plVector3 v1,plVector3 v2);
+ extern plCollisionShapeHandle plNewStaticTriangleMeshShape(plMeshInterfaceHandle);
+
+ extern void plSetScaling(plCollisionShapeHandle shape, plVector3 scaling);
+
+/* SOLID has Response Callback/Table/Management */
+/* PhysX has Triggers, User Callbacks and filtering */
+/* ODE has the typedef void dNearCallback (void *data, dGeomID o1, dGeomID o2); */
+
+/* typedef void plUpdatedPositionCallback(void* userData, plRigidBodyHandle rbHandle, plVector3 pos); */
+/* typedef void plUpdatedOrientationCallback(void* userData, plRigidBodyHandle rbHandle, plQuaternion orientation); */
+
+ /* get world transform */
+ extern void plGetOpenGLMatrix(plRigidBodyHandle object, plReal* matrix);
+ extern void plGetPosition(plRigidBodyHandle object,plVector3 position);
+ extern void plGetOrientation(plRigidBodyHandle object,plQuaternion orientation);
+
+ /* set world transform (position/orientation) */
+ extern void plSetPosition(plRigidBodyHandle object, const plVector3 position);
+ extern void plSetOrientation(plRigidBodyHandle object, const plQuaternion orientation);
+ extern void plSetEuler(plReal yaw,plReal pitch,plReal roll, plQuaternion orient);
+ extern void plSetOpenGLMatrix(plRigidBodyHandle object, plReal* matrix);
+
+ typedef struct plRayCastResult {
+ plRigidBodyHandle m_body;
+ plCollisionShapeHandle m_shape;
+ plVector3 m_positionWorld;
+ plVector3 m_normalWorld;
+ } plRayCastResult;
+
+ extern int plRayCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plRayCastResult res);
+
+ /* Sweep API */
+
+ /* extern plRigidBodyHandle plObjectCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plVector3 hitpoint, plVector3 normal); */
+
+ /* Continuous Collision Detection API */
+
+ // needed for source/blender/blenkernel/intern/collision.c
+ double plNearestPoints(float p1[3], float p2[3], float p3[3], float q1[3], float q2[3], float q3[3], float *pa, float *pb, float normal[3]);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif //BULLET_C_API_H
+
diff --git a/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp
new file mode 100644
index 00000000..77763305
--- /dev/null
+++ b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp
@@ -0,0 +1,37 @@
+
+//Bullet Continuous Collision Detection and Physics Library
+//Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+
+//
+// btAxisSweep3
+//
+// Copyright (c) 2006 Simon Hobbs
+//
+// This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source distribution.
+#include "btAxisSweep3.h"
+
+
+btAxisSweep3::btAxisSweep3(const btVector3& worldAabbMin,const btVector3& worldAabbMax, unsigned short int maxHandles, btOverlappingPairCache* pairCache, bool disableRaycastAccelerator)
+:btAxisSweep3Internal(worldAabbMin,worldAabbMax,0xfffe,0xffff,maxHandles,pairCache,disableRaycastAccelerator)
+{
+ // 1 handle is reserved as sentinel
+ btAssert(maxHandles > 1 && maxHandles < 32767);
+
+}
+
+
+bt32BitAxisSweep3::bt32BitAxisSweep3(const btVector3& worldAabbMin,const btVector3& worldAabbMax, unsigned int maxHandles , btOverlappingPairCache* pairCache , bool disableRaycastAccelerator)
+:btAxisSweep3Internal(worldAabbMin,worldAabbMax,0xfffffffe,0x7fffffff,maxHandles,pairCache,disableRaycastAccelerator)
+{
+ // 1 handle is reserved as sentinel
+ btAssert(maxHandles > 1 && maxHandles < 2147483647);
+}
diff --git a/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btAxisSweep3.h b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btAxisSweep3.h
new file mode 100644
index 00000000..cd6e1a89
--- /dev/null
+++ b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btAxisSweep3.h
@@ -0,0 +1,1051 @@
+//Bullet Continuous Collision Detection and Physics Library
+//Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+//
+// btAxisSweep3.h
+//
+// Copyright (c) 2006 Simon Hobbs
+//
+// This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source distribution.
+
+#ifndef BT_AXIS_SWEEP_3_H
+#define BT_AXIS_SWEEP_3_H
+
+#include "LinearMath/btVector3.h"
+#include "btOverlappingPairCache.h"
+#include "btBroadphaseInterface.h"
+#include "btBroadphaseProxy.h"
+#include "btOverlappingPairCallback.h"
+#include "btDbvtBroadphase.h"
+
+//#define DEBUG_BROADPHASE 1
+#define USE_OVERLAP_TEST_ON_REMOVES 1
+
+/// The internal templace class btAxisSweep3Internal implements the sweep and prune broadphase.
+/// It uses quantized integers to represent the begin and end points for each of the 3 axis.
+/// Dont use this class directly, use btAxisSweep3 or bt32BitAxisSweep3 instead.
+template
+class btAxisSweep3Internal : public btBroadphaseInterface
+{
+protected:
+
+ BP_FP_INT_TYPE m_bpHandleMask;
+ BP_FP_INT_TYPE m_handleSentinel;
+
+public:
+
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ class Edge
+ {
+ public:
+ BP_FP_INT_TYPE m_pos; // low bit is min/max
+ BP_FP_INT_TYPE m_handle;
+
+ BP_FP_INT_TYPE IsMax() const {return static_cast(m_pos & 1);}
+ };
+
+public:
+ class Handle : public btBroadphaseProxy
+ {
+ public:
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ // indexes into the edge arrays
+ BP_FP_INT_TYPE m_minEdges[3], m_maxEdges[3]; // 6 * 2 = 12
+// BP_FP_INT_TYPE m_uniqueId;
+ btBroadphaseProxy* m_dbvtProxy;//for faster raycast
+ //void* m_pOwner; this is now in btBroadphaseProxy.m_clientObject
+
+ SIMD_FORCE_INLINE void SetNextFree(BP_FP_INT_TYPE next) {m_minEdges[0] = next;}
+ SIMD_FORCE_INLINE BP_FP_INT_TYPE GetNextFree() const {return m_minEdges[0];}
+ }; // 24 bytes + 24 for Edge structures = 44 bytes total per entry
+
+
+protected:
+ btVector3 m_worldAabbMin; // overall system bounds
+ btVector3 m_worldAabbMax; // overall system bounds
+
+ btVector3 m_quantize; // scaling factor for quantization
+
+ BP_FP_INT_TYPE m_numHandles; // number of active handles
+ BP_FP_INT_TYPE m_maxHandles; // max number of handles
+ Handle* m_pHandles; // handles pool
+
+ BP_FP_INT_TYPE m_firstFreeHandle; // free handles list
+
+ Edge* m_pEdges[3]; // edge arrays for the 3 axes (each array has m_maxHandles * 2 + 2 sentinel entries)
+ void* m_pEdgesRawPtr[3];
+
+ btOverlappingPairCache* m_pairCache;
+
+ ///btOverlappingPairCallback is an additional optional user callback for adding/removing overlapping pairs, similar interface to btOverlappingPairCache.
+ btOverlappingPairCallback* m_userPairCallback;
+
+ bool m_ownsPairCache;
+
+ int m_invalidPair;
+
+ ///additional dynamic aabb structure, used to accelerate ray cast queries.
+ ///can be disabled using a optional argument in the constructor
+ btDbvtBroadphase* m_raycastAccelerator;
+ btOverlappingPairCache* m_nullPairCache;
+
+
+ // allocation/deallocation
+ BP_FP_INT_TYPE allocHandle();
+ void freeHandle(BP_FP_INT_TYPE handle);
+
+
+ bool testOverlap2D(const Handle* pHandleA, const Handle* pHandleB,int axis0,int axis1);
+
+#ifdef DEBUG_BROADPHASE
+ void debugPrintAxis(int axis,bool checkCardinality=true);
+#endif //DEBUG_BROADPHASE
+
+ //Overlap* AddOverlap(BP_FP_INT_TYPE handleA, BP_FP_INT_TYPE handleB);
+ //void RemoveOverlap(BP_FP_INT_TYPE handleA, BP_FP_INT_TYPE handleB);
+
+
+
+ void sortMinDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps );
+ void sortMinUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps );
+ void sortMaxDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps );
+ void sortMaxUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps );
+
+public:
+
+ btAxisSweep3Internal(const btVector3& worldAabbMin,const btVector3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel, BP_FP_INT_TYPE maxHandles = 16384, btOverlappingPairCache* pairCache=0,bool disableRaycastAccelerator = false);
+
+ virtual ~btAxisSweep3Internal();
+
+ BP_FP_INT_TYPE getNumHandles() const
+ {
+ return m_numHandles;
+ }
+
+ virtual void calculateOverlappingPairs(btDispatcher* dispatcher);
+
+ BP_FP_INT_TYPE addHandle(const btVector3& aabbMin,const btVector3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy);
+ void removeHandle(BP_FP_INT_TYPE handle,btDispatcher* dispatcher);
+ void updateHandle(BP_FP_INT_TYPE handle, const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher);
+ SIMD_FORCE_INLINE Handle* getHandle(BP_FP_INT_TYPE index) const {return m_pHandles + index;}
+
+ virtual void resetPool(btDispatcher* dispatcher);
+
+ void processAllOverlappingPairs(btOverlapCallback* callback);
+
+ //Broadphase Interface
+ virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy);
+ virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+ virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher);
+ virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const;
+
+ virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0), const btVector3& aabbMax = btVector3(0,0,0));
+ virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback);
+
+
+ void quantize(BP_FP_INT_TYPE* out, const btVector3& point, int isMax) const;
+ ///unQuantize should be conservative: aabbMin/aabbMax should be larger then 'getAabb' result
+ void unQuantize(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const;
+
+ bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
+
+ btOverlappingPairCache* getOverlappingPairCache()
+ {
+ return m_pairCache;
+ }
+ const btOverlappingPairCache* getOverlappingPairCache() const
+ {
+ return m_pairCache;
+ }
+
+ void setOverlappingPairUserCallback(btOverlappingPairCallback* pairCallback)
+ {
+ m_userPairCallback = pairCallback;
+ }
+ const btOverlappingPairCallback* getOverlappingPairUserCallback() const
+ {
+ return m_userPairCallback;
+ }
+
+ ///getAabb returns the axis aligned bounding box in the 'global' coordinate frame
+ ///will add some transform later
+ virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const
+ {
+ aabbMin = m_worldAabbMin;
+ aabbMax = m_worldAabbMax;
+ }
+
+ virtual void printStats()
+ {
+/* printf("btAxisSweep3.h\n");
+ printf("numHandles = %d, maxHandles = %d\n",m_numHandles,m_maxHandles);
+ printf("aabbMin=%f,%f,%f,aabbMax=%f,%f,%f\n",m_worldAabbMin.getX(),m_worldAabbMin.getY(),m_worldAabbMin.getZ(),
+ m_worldAabbMax.getX(),m_worldAabbMax.getY(),m_worldAabbMax.getZ());
+ */
+
+ }
+
+};
+
+////////////////////////////////////////////////////////////////////
+
+
+
+
+#ifdef DEBUG_BROADPHASE
+#include
+
+template
+void btAxisSweep3::debugPrintAxis(int axis, bool checkCardinality)
+{
+ int numEdges = m_pHandles[0].m_maxEdges[axis];
+ printf("SAP Axis %d, numEdges=%d\n",axis,numEdges);
+
+ int i;
+ for (i=0;im_handle);
+ int handleIndex = pEdge->IsMax()? pHandlePrev->m_maxEdges[axis] : pHandlePrev->m_minEdges[axis];
+ char beginOrEnd;
+ beginOrEnd=pEdge->IsMax()?'E':'B';
+ printf(" [%c,h=%d,p=%x,i=%d]\n",beginOrEnd,pEdge->m_handle,pEdge->m_pos,handleIndex);
+ }
+
+ if (checkCardinality)
+ btAssert(numEdges == m_numHandles*2+1);
+}
+#endif //DEBUG_BROADPHASE
+
+template
+btBroadphaseProxy* btAxisSweep3Internal::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy)
+{
+ (void)shapeType;
+ BP_FP_INT_TYPE handleId = addHandle(aabbMin,aabbMax, userPtr,collisionFilterGroup,collisionFilterMask,dispatcher,multiSapProxy);
+
+ Handle* handle = getHandle(handleId);
+
+ if (m_raycastAccelerator)
+ {
+ btBroadphaseProxy* rayProxy = m_raycastAccelerator->createProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask,dispatcher,0);
+ handle->m_dbvtProxy = rayProxy;
+ }
+ return handle;
+}
+
+
+
+template
+void btAxisSweep3Internal::destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
+{
+ Handle* handle = static_cast(proxy);
+ if (m_raycastAccelerator)
+ m_raycastAccelerator->destroyProxy(handle->m_dbvtProxy,dispatcher);
+ removeHandle(static_cast(handle->m_uniqueId), dispatcher);
+}
+
+template
+void btAxisSweep3Internal::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher)
+{
+ Handle* handle = static_cast(proxy);
+ handle->m_aabbMin = aabbMin;
+ handle->m_aabbMax = aabbMax;
+ updateHandle(static_cast(handle->m_uniqueId), aabbMin, aabbMax,dispatcher);
+ if (m_raycastAccelerator)
+ m_raycastAccelerator->setAabb(handle->m_dbvtProxy,aabbMin,aabbMax,dispatcher);
+
+}
+
+template
+void btAxisSweep3Internal::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback,const btVector3& aabbMin,const btVector3& aabbMax)
+{
+ if (m_raycastAccelerator)
+ {
+ m_raycastAccelerator->rayTest(rayFrom,rayTo,rayCallback,aabbMin,aabbMax);
+ } else
+ {
+ //choose axis?
+ BP_FP_INT_TYPE axis = 0;
+ //for each proxy
+ for (BP_FP_INT_TYPE i=1;i
+void btAxisSweep3Internal::aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback)
+{
+ if (m_raycastAccelerator)
+ {
+ m_raycastAccelerator->aabbTest(aabbMin,aabbMax,callback);
+ } else
+ {
+ //choose axis?
+ BP_FP_INT_TYPE axis = 0;
+ //for each proxy
+ for (BP_FP_INT_TYPE i=1;im_aabbMin,handle->m_aabbMax))
+ {
+ callback.process(handle);
+ }
+ }
+ }
+ }
+}
+
+
+
+template
+void btAxisSweep3Internal::getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const
+{
+ Handle* pHandle = static_cast(proxy);
+ aabbMin = pHandle->m_aabbMin;
+ aabbMax = pHandle->m_aabbMax;
+}
+
+
+template
+void btAxisSweep3Internal::unQuantize(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const
+{
+ Handle* pHandle = static_cast(proxy);
+
+ unsigned short vecInMin[3];
+ unsigned short vecInMax[3];
+
+ vecInMin[0] = m_pEdges[0][pHandle->m_minEdges[0]].m_pos ;
+ vecInMax[0] = m_pEdges[0][pHandle->m_maxEdges[0]].m_pos +1 ;
+ vecInMin[1] = m_pEdges[1][pHandle->m_minEdges[1]].m_pos ;
+ vecInMax[1] = m_pEdges[1][pHandle->m_maxEdges[1]].m_pos +1 ;
+ vecInMin[2] = m_pEdges[2][pHandle->m_minEdges[2]].m_pos ;
+ vecInMax[2] = m_pEdges[2][pHandle->m_maxEdges[2]].m_pos +1 ;
+
+ aabbMin.setValue((btScalar)(vecInMin[0]) / (m_quantize.getX()),(btScalar)(vecInMin[1]) / (m_quantize.getY()),(btScalar)(vecInMin[2]) / (m_quantize.getZ()));
+ aabbMin += m_worldAabbMin;
+
+ aabbMax.setValue((btScalar)(vecInMax[0]) / (m_quantize.getX()),(btScalar)(vecInMax[1]) / (m_quantize.getY()),(btScalar)(vecInMax[2]) / (m_quantize.getZ()));
+ aabbMax += m_worldAabbMin;
+}
+
+
+
+
+template
+btAxisSweep3Internal::btAxisSweep3Internal(const btVector3& worldAabbMin,const btVector3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel,BP_FP_INT_TYPE userMaxHandles, btOverlappingPairCache* pairCache , bool disableRaycastAccelerator)
+:m_bpHandleMask(handleMask),
+m_handleSentinel(handleSentinel),
+m_pairCache(pairCache),
+m_userPairCallback(0),
+m_ownsPairCache(false),
+m_invalidPair(0),
+m_raycastAccelerator(0)
+{
+ BP_FP_INT_TYPE maxHandles = static_cast(userMaxHandles+1);//need to add one sentinel handle
+
+ if (!m_pairCache)
+ {
+ void* ptr = btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16);
+ m_pairCache = new(ptr) btHashedOverlappingPairCache();
+ m_ownsPairCache = true;
+ }
+
+ if (!disableRaycastAccelerator)
+ {
+ m_nullPairCache = new (btAlignedAlloc(sizeof(btNullPairCache),16)) btNullPairCache();
+ m_raycastAccelerator = new (btAlignedAlloc(sizeof(btDbvtBroadphase),16)) btDbvtBroadphase(m_nullPairCache);//m_pairCache);
+ m_raycastAccelerator->m_deferedcollide = true;//don't add/remove pairs
+ }
+
+ //btAssert(bounds.HasVolume());
+
+ // init bounds
+ m_worldAabbMin = worldAabbMin;
+ m_worldAabbMax = worldAabbMax;
+
+ btVector3 aabbSize = m_worldAabbMax - m_worldAabbMin;
+
+ BP_FP_INT_TYPE maxInt = m_handleSentinel;
+
+ m_quantize = btVector3(btScalar(maxInt),btScalar(maxInt),btScalar(maxInt)) / aabbSize;
+
+ // allocate handles buffer, using btAlignedAlloc, and put all handles on free list
+ m_pHandles = new Handle[maxHandles];
+
+ m_maxHandles = maxHandles;
+ m_numHandles = 0;
+
+ // handle 0 is reserved as the null index, and is also used as the sentinel
+ m_firstFreeHandle = 1;
+ {
+ for (BP_FP_INT_TYPE i = m_firstFreeHandle; i < maxHandles; i++)
+ m_pHandles[i].SetNextFree(static_cast(i + 1));
+ m_pHandles[maxHandles - 1].SetNextFree(0);
+ }
+
+ {
+ // allocate edge buffers
+ for (int i = 0; i < 3; i++)
+ {
+ m_pEdgesRawPtr[i] = btAlignedAlloc(sizeof(Edge)*maxHandles*2,16);
+ m_pEdges[i] = new(m_pEdgesRawPtr[i]) Edge[maxHandles * 2];
+ }
+ }
+ //removed overlap management
+
+ // make boundary sentinels
+
+ m_pHandles[0].m_clientObject = 0;
+
+ for (int axis = 0; axis < 3; axis++)
+ {
+ m_pHandles[0].m_minEdges[axis] = 0;
+ m_pHandles[0].m_maxEdges[axis] = 1;
+
+ m_pEdges[axis][0].m_pos = 0;
+ m_pEdges[axis][0].m_handle = 0;
+ m_pEdges[axis][1].m_pos = m_handleSentinel;
+ m_pEdges[axis][1].m_handle = 0;
+#ifdef DEBUG_BROADPHASE
+ debugPrintAxis(axis);
+#endif //DEBUG_BROADPHASE
+
+ }
+
+}
+
+template
+btAxisSweep3Internal::~btAxisSweep3Internal()
+{
+ if (m_raycastAccelerator)
+ {
+ m_nullPairCache->~btOverlappingPairCache();
+ btAlignedFree(m_nullPairCache);
+ m_raycastAccelerator->~btDbvtBroadphase();
+ btAlignedFree (m_raycastAccelerator);
+ }
+
+ for (int i = 2; i >= 0; i--)
+ {
+ btAlignedFree(m_pEdgesRawPtr[i]);
+ }
+ delete [] m_pHandles;
+
+ if (m_ownsPairCache)
+ {
+ m_pairCache->~btOverlappingPairCache();
+ btAlignedFree(m_pairCache);
+ }
+}
+
+template
+void btAxisSweep3Internal::quantize(BP_FP_INT_TYPE* out, const btVector3& point, int isMax) const
+{
+#ifdef OLD_CLAMPING_METHOD
+ ///problem with this clamping method is that the floating point during quantization might still go outside the range [(0|isMax) .. (m_handleSentinel&m_bpHandleMask]|isMax]
+ ///see http://code.google.com/p/bullet/issues/detail?id=87
+ btVector3 clampedPoint(point);
+ clampedPoint.setMax(m_worldAabbMin);
+ clampedPoint.setMin(m_worldAabbMax);
+ btVector3 v = (clampedPoint - m_worldAabbMin) * m_quantize;
+ out[0] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getX() & m_bpHandleMask) | isMax);
+ out[1] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getY() & m_bpHandleMask) | isMax);
+ out[2] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getZ() & m_bpHandleMask) | isMax);
+#else
+ btVector3 v = (point - m_worldAabbMin) * m_quantize;
+ out[0]=(v[0]<=0)?(BP_FP_INT_TYPE)isMax:(v[0]>=m_handleSentinel)?(BP_FP_INT_TYPE)((m_handleSentinel&m_bpHandleMask)|isMax):(BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v[0]&m_bpHandleMask)|isMax);
+ out[1]=(v[1]<=0)?(BP_FP_INT_TYPE)isMax:(v[1]>=m_handleSentinel)?(BP_FP_INT_TYPE)((m_handleSentinel&m_bpHandleMask)|isMax):(BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v[1]&m_bpHandleMask)|isMax);
+ out[2]=(v[2]<=0)?(BP_FP_INT_TYPE)isMax:(v[2]>=m_handleSentinel)?(BP_FP_INT_TYPE)((m_handleSentinel&m_bpHandleMask)|isMax):(BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v[2]&m_bpHandleMask)|isMax);
+#endif //OLD_CLAMPING_METHOD
+}
+
+
+template
+BP_FP_INT_TYPE btAxisSweep3Internal::allocHandle()
+{
+ btAssert(m_firstFreeHandle);
+
+ BP_FP_INT_TYPE handle = m_firstFreeHandle;
+ m_firstFreeHandle = getHandle(handle)->GetNextFree();
+ m_numHandles++;
+
+ return handle;
+}
+
+template
+void btAxisSweep3Internal::freeHandle(BP_FP_INT_TYPE handle)
+{
+ btAssert(handle > 0 && handle < m_maxHandles);
+
+ getHandle(handle)->SetNextFree(m_firstFreeHandle);
+ m_firstFreeHandle = handle;
+
+ m_numHandles--;
+}
+
+
+template
+BP_FP_INT_TYPE btAxisSweep3Internal::addHandle(const btVector3& aabbMin,const btVector3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy)
+{
+ // quantize the bounds
+ BP_FP_INT_TYPE min[3], max[3];
+ quantize(min, aabbMin, 0);
+ quantize(max, aabbMax, 1);
+
+ // allocate a handle
+ BP_FP_INT_TYPE handle = allocHandle();
+
+
+ Handle* pHandle = getHandle(handle);
+
+ pHandle->m_uniqueId = static_cast(handle);
+ //pHandle->m_pOverlaps = 0;
+ pHandle->m_clientObject = pOwner;
+ pHandle->m_collisionFilterGroup = collisionFilterGroup;
+ pHandle->m_collisionFilterMask = collisionFilterMask;
+ pHandle->m_multiSapParentProxy = multiSapProxy;
+
+ // compute current limit of edge arrays
+ BP_FP_INT_TYPE limit = static_cast(m_numHandles * 2);
+
+
+ // insert new edges just inside the max boundary edge
+ for (BP_FP_INT_TYPE axis = 0; axis < 3; axis++)
+ {
+
+ m_pHandles[0].m_maxEdges[axis] += 2;
+
+ m_pEdges[axis][limit + 1] = m_pEdges[axis][limit - 1];
+
+ m_pEdges[axis][limit - 1].m_pos = min[axis];
+ m_pEdges[axis][limit - 1].m_handle = handle;
+
+ m_pEdges[axis][limit].m_pos = max[axis];
+ m_pEdges[axis][limit].m_handle = handle;
+
+ pHandle->m_minEdges[axis] = static_cast(limit - 1);
+ pHandle->m_maxEdges[axis] = limit;
+ }
+
+ // now sort the new edges to their correct position
+ sortMinDown(0, pHandle->m_minEdges[0], dispatcher,false);
+ sortMaxDown(0, pHandle->m_maxEdges[0], dispatcher,false);
+ sortMinDown(1, pHandle->m_minEdges[1], dispatcher,false);
+ sortMaxDown(1, pHandle->m_maxEdges[1], dispatcher,false);
+ sortMinDown(2, pHandle->m_minEdges[2], dispatcher,true);
+ sortMaxDown(2, pHandle->m_maxEdges[2], dispatcher,true);
+
+
+ return handle;
+}
+
+
+template
+void btAxisSweep3Internal::removeHandle(BP_FP_INT_TYPE handle,btDispatcher* dispatcher)
+{
+
+ Handle* pHandle = getHandle(handle);
+
+ //explicitly remove the pairs containing the proxy
+ //we could do it also in the sortMinUp (passing true)
+ ///@todo: compare performance
+ if (!m_pairCache->hasDeferredRemoval())
+ {
+ m_pairCache->removeOverlappingPairsContainingProxy(pHandle,dispatcher);
+ }
+
+ // compute current limit of edge arrays
+ int limit = static_cast(m_numHandles * 2);
+
+ int axis;
+
+ for (axis = 0;axis<3;axis++)
+ {
+ m_pHandles[0].m_maxEdges[axis] -= 2;
+ }
+
+ // remove the edges by sorting them up to the end of the list
+ for ( axis = 0; axis < 3; axis++)
+ {
+ Edge* pEdges = m_pEdges[axis];
+ BP_FP_INT_TYPE max = pHandle->m_maxEdges[axis];
+ pEdges[max].m_pos = m_handleSentinel;
+
+ sortMaxUp(axis,max,dispatcher,false);
+
+
+ BP_FP_INT_TYPE i = pHandle->m_minEdges[axis];
+ pEdges[i].m_pos = m_handleSentinel;
+
+
+ sortMinUp(axis,i,dispatcher,false);
+
+ pEdges[limit-1].m_handle = 0;
+ pEdges[limit-1].m_pos = m_handleSentinel;
+
+#ifdef DEBUG_BROADPHASE
+ debugPrintAxis(axis,false);
+#endif //DEBUG_BROADPHASE
+
+
+ }
+
+
+ // free the handle
+ freeHandle(handle);
+
+
+}
+
+template
+void btAxisSweep3Internal::resetPool(btDispatcher* /*dispatcher*/)
+{
+ if (m_numHandles == 0)
+ {
+ m_firstFreeHandle = 1;
+ {
+ for (BP_FP_INT_TYPE i = m_firstFreeHandle; i < m_maxHandles; i++)
+ m_pHandles[i].SetNextFree(static_cast(i + 1));
+ m_pHandles[m_maxHandles - 1].SetNextFree(0);
+ }
+ }
+}
+
+
+extern int gOverlappingPairs;
+//#include
+
+template
+void btAxisSweep3Internal::calculateOverlappingPairs(btDispatcher* dispatcher)
+{
+
+ if (m_pairCache->hasDeferredRemoval())
+ {
+
+ btBroadphasePairArray& overlappingPairArray = m_pairCache->getOverlappingPairArray();
+
+ //perform a sort, to find duplicates and to sort 'invalid' pairs to the end
+ overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
+
+ overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
+ m_invalidPair = 0;
+
+
+ int i;
+
+ btBroadphasePair previousPair;
+ previousPair.m_pProxy0 = 0;
+ previousPair.m_pProxy1 = 0;
+ previousPair.m_algorithm = 0;
+
+
+ for (i=0;iprocessOverlap(pair);
+ } else
+ {
+ needsRemoval = true;
+ }
+ } else
+ {
+ //remove duplicate
+ needsRemoval = true;
+ //should have no algorithm
+ btAssert(!pair.m_algorithm);
+ }
+
+ if (needsRemoval)
+ {
+ m_pairCache->cleanOverlappingPair(pair,dispatcher);
+
+ // m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
+ // m_overlappingPairArray.pop_back();
+ pair.m_pProxy0 = 0;
+ pair.m_pProxy1 = 0;
+ m_invalidPair++;
+ gOverlappingPairs--;
+ }
+
+ }
+
+ ///if you don't like to skip the invalid pairs in the array, execute following code:
+ #define CLEAN_INVALID_PAIRS 1
+ #ifdef CLEAN_INVALID_PAIRS
+
+ //perform a sort, to sort 'invalid' pairs to the end
+ overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
+
+ overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
+ m_invalidPair = 0;
+ #endif//CLEAN_INVALID_PAIRS
+
+ //printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size());
+ }
+
+}
+
+
+template
+bool btAxisSweep3Internal::testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
+{
+ const Handle* pHandleA = static_cast(proxy0);
+ const Handle* pHandleB = static_cast(proxy1);
+
+ //optimization 1: check the array index (memory address), instead of the m_pos
+
+ for (int axis = 0; axis < 3; axis++)
+ {
+ if (pHandleA->m_maxEdges[axis] < pHandleB->m_minEdges[axis] ||
+ pHandleB->m_maxEdges[axis] < pHandleA->m_minEdges[axis])
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+template
+bool btAxisSweep3Internal::testOverlap2D(const Handle* pHandleA, const Handle* pHandleB,int axis0,int axis1)
+{
+ //optimization 1: check the array index (memory address), instead of the m_pos
+
+ if (pHandleA->m_maxEdges[axis0] < pHandleB->m_minEdges[axis0] ||
+ pHandleB->m_maxEdges[axis0] < pHandleA->m_minEdges[axis0] ||
+ pHandleA->m_maxEdges[axis1] < pHandleB->m_minEdges[axis1] ||
+ pHandleB->m_maxEdges[axis1] < pHandleA->m_minEdges[axis1])
+ {
+ return false;
+ }
+ return true;
+}
+
+template
+void btAxisSweep3Internal::updateHandle(BP_FP_INT_TYPE handle, const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher)
+{
+// btAssert(bounds.IsFinite());
+ //btAssert(bounds.HasVolume());
+
+ Handle* pHandle = getHandle(handle);
+
+ // quantize the new bounds
+ BP_FP_INT_TYPE min[3], max[3];
+ quantize(min, aabbMin, 0);
+ quantize(max, aabbMax, 1);
+
+ // update changed edges
+ for (int axis = 0; axis < 3; axis++)
+ {
+ BP_FP_INT_TYPE emin = pHandle->m_minEdges[axis];
+ BP_FP_INT_TYPE emax = pHandle->m_maxEdges[axis];
+
+ int dmin = (int)min[axis] - (int)m_pEdges[axis][emin].m_pos;
+ int dmax = (int)max[axis] - (int)m_pEdges[axis][emax].m_pos;
+
+ m_pEdges[axis][emin].m_pos = min[axis];
+ m_pEdges[axis][emax].m_pos = max[axis];
+
+ // expand (only adds overlaps)
+ if (dmin < 0)
+ sortMinDown(axis, emin,dispatcher,true);
+
+ if (dmax > 0)
+ sortMaxUp(axis, emax,dispatcher,true);
+
+ // shrink (only removes overlaps)
+ if (dmin > 0)
+ sortMinUp(axis, emin,dispatcher,true);
+
+ if (dmax < 0)
+ sortMaxDown(axis, emax,dispatcher,true);
+
+#ifdef DEBUG_BROADPHASE
+ debugPrintAxis(axis);
+#endif //DEBUG_BROADPHASE
+ }
+
+
+}
+
+
+
+
+// sorting a min edge downwards can only ever *add* overlaps
+template
+void btAxisSweep3Internal::sortMinDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* /* dispatcher */, bool updateOverlaps)
+{
+
+ Edge* pEdge = m_pEdges[axis] + edge;
+ Edge* pPrev = pEdge - 1;
+ Handle* pHandleEdge = getHandle(pEdge->m_handle);
+
+ while (pEdge->m_pos < pPrev->m_pos)
+ {
+ Handle* pHandlePrev = getHandle(pPrev->m_handle);
+
+ if (pPrev->IsMax())
+ {
+ // if previous edge is a maximum check the bounds and add an overlap if necessary
+ const int axis1 = (1 << axis) & 3;
+ const int axis2 = (1 << axis1) & 3;
+ if (updateOverlaps && testOverlap2D(pHandleEdge, pHandlePrev,axis1,axis2))
+ {
+ m_pairCache->addOverlappingPair(pHandleEdge,pHandlePrev);
+ if (m_userPairCallback)
+ m_userPairCallback->addOverlappingPair(pHandleEdge,pHandlePrev);
+
+ //AddOverlap(pEdge->m_handle, pPrev->m_handle);
+
+ }
+
+ // update edge reference in other handle
+ pHandlePrev->m_maxEdges[axis]++;
+ }
+ else
+ pHandlePrev->m_minEdges[axis]++;
+
+ pHandleEdge->m_minEdges[axis]--;
+
+ // swap the edges
+ Edge swap = *pEdge;
+ *pEdge = *pPrev;
+ *pPrev = swap;
+
+ // decrement
+ pEdge--;
+ pPrev--;
+ }
+
+#ifdef DEBUG_BROADPHASE
+ debugPrintAxis(axis);
+#endif //DEBUG_BROADPHASE
+
+}
+
+// sorting a min edge upwards can only ever *remove* overlaps
+template
+void btAxisSweep3Internal::sortMinUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps)
+{
+ Edge* pEdge = m_pEdges[axis] + edge;
+ Edge* pNext = pEdge + 1;
+ Handle* pHandleEdge = getHandle(pEdge->m_handle);
+
+ while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos))
+ {
+ Handle* pHandleNext = getHandle(pNext->m_handle);
+
+ if (pNext->IsMax())
+ {
+ Handle* handle0 = getHandle(pEdge->m_handle);
+ Handle* handle1 = getHandle(pNext->m_handle);
+ const int axis1 = (1 << axis) & 3;
+ const int axis2 = (1 << axis1) & 3;
+
+ // if next edge is maximum remove any overlap between the two handles
+ if (updateOverlaps
+#ifdef USE_OVERLAP_TEST_ON_REMOVES
+ && testOverlap2D(handle0,handle1,axis1,axis2)
+#endif //USE_OVERLAP_TEST_ON_REMOVES
+ )
+ {
+
+
+ m_pairCache->removeOverlappingPair(handle0,handle1,dispatcher);
+ if (m_userPairCallback)
+ m_userPairCallback->removeOverlappingPair(handle0,handle1,dispatcher);
+
+ }
+
+
+ // update edge reference in other handle
+ pHandleNext->m_maxEdges[axis]--;
+ }
+ else
+ pHandleNext->m_minEdges[axis]--;
+
+ pHandleEdge->m_minEdges[axis]++;
+
+ // swap the edges
+ Edge swap = *pEdge;
+ *pEdge = *pNext;
+ *pNext = swap;
+
+ // increment
+ pEdge++;
+ pNext++;
+ }
+
+
+}
+
+// sorting a max edge downwards can only ever *remove* overlaps
+template
+void btAxisSweep3Internal::sortMaxDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps)
+{
+
+ Edge* pEdge = m_pEdges[axis] + edge;
+ Edge* pPrev = pEdge - 1;
+ Handle* pHandleEdge = getHandle(pEdge->m_handle);
+
+ while (pEdge->m_pos < pPrev->m_pos)
+ {
+ Handle* pHandlePrev = getHandle(pPrev->m_handle);
+
+ if (!pPrev->IsMax())
+ {
+ // if previous edge was a minimum remove any overlap between the two handles
+ Handle* handle0 = getHandle(pEdge->m_handle);
+ Handle* handle1 = getHandle(pPrev->m_handle);
+ const int axis1 = (1 << axis) & 3;
+ const int axis2 = (1 << axis1) & 3;
+
+ if (updateOverlaps
+#ifdef USE_OVERLAP_TEST_ON_REMOVES
+ && testOverlap2D(handle0,handle1,axis1,axis2)
+#endif //USE_OVERLAP_TEST_ON_REMOVES
+ )
+ {
+ //this is done during the overlappingpairarray iteration/narrowphase collision
+
+
+ m_pairCache->removeOverlappingPair(handle0,handle1,dispatcher);
+ if (m_userPairCallback)
+ m_userPairCallback->removeOverlappingPair(handle0,handle1,dispatcher);
+
+
+
+ }
+
+ // update edge reference in other handle
+ pHandlePrev->m_minEdges[axis]++;;
+ }
+ else
+ pHandlePrev->m_maxEdges[axis]++;
+
+ pHandleEdge->m_maxEdges[axis]--;
+
+ // swap the edges
+ Edge swap = *pEdge;
+ *pEdge = *pPrev;
+ *pPrev = swap;
+
+ // decrement
+ pEdge--;
+ pPrev--;
+ }
+
+
+#ifdef DEBUG_BROADPHASE
+ debugPrintAxis(axis);
+#endif //DEBUG_BROADPHASE
+
+}
+
+// sorting a max edge upwards can only ever *add* overlaps
+template
+void btAxisSweep3Internal::sortMaxUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* /* dispatcher */, bool updateOverlaps)
+{
+ Edge* pEdge = m_pEdges[axis] + edge;
+ Edge* pNext = pEdge + 1;
+ Handle* pHandleEdge = getHandle(pEdge->m_handle);
+
+ while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos))
+ {
+ Handle* pHandleNext = getHandle(pNext->m_handle);
+
+ const int axis1 = (1 << axis) & 3;
+ const int axis2 = (1 << axis1) & 3;
+
+ if (!pNext->IsMax())
+ {
+ // if next edge is a minimum check the bounds and add an overlap if necessary
+ if (updateOverlaps && testOverlap2D(pHandleEdge, pHandleNext,axis1,axis2))
+ {
+ Handle* handle0 = getHandle(pEdge->m_handle);
+ Handle* handle1 = getHandle(pNext->m_handle);
+ m_pairCache->addOverlappingPair(handle0,handle1);
+ if (m_userPairCallback)
+ m_userPairCallback->addOverlappingPair(handle0,handle1);
+ }
+
+ // update edge reference in other handle
+ pHandleNext->m_minEdges[axis]--;
+ }
+ else
+ pHandleNext->m_maxEdges[axis]--;
+
+ pHandleEdge->m_maxEdges[axis]++;
+
+ // swap the edges
+ Edge swap = *pEdge;
+ *pEdge = *pNext;
+ *pNext = swap;
+
+ // increment
+ pEdge++;
+ pNext++;
+ }
+
+}
+
+
+
+////////////////////////////////////////////////////////////////////
+
+
+/// The btAxisSweep3 is an efficient implementation of the 3d axis sweep and prune broadphase.
+/// It uses arrays rather then lists for storage of the 3 axis. Also it operates using 16 bit integer coordinates instead of floats.
+/// For large worlds and many objects, use bt32BitAxisSweep3 or btDbvtBroadphase instead. bt32BitAxisSweep3 has higher precision and allows more then 16384 objects at the cost of more memory and bit of performance.
+class btAxisSweep3 : public btAxisSweep3Internal
+{
+public:
+
+ btAxisSweep3(const btVector3& worldAabbMin,const btVector3& worldAabbMax, unsigned short int maxHandles = 16384, btOverlappingPairCache* pairCache = 0, bool disableRaycastAccelerator = false);
+
+};
+
+/// The bt32BitAxisSweep3 allows higher precision quantization and more objects compared to the btAxisSweep3 sweep and prune.
+/// This comes at the cost of more memory per handle, and a bit slower performance.
+/// It uses arrays rather then lists for storage of the 3 axis.
+class bt32BitAxisSweep3 : public btAxisSweep3Internal
+{
+public:
+
+ bt32BitAxisSweep3(const btVector3& worldAabbMin,const btVector3& worldAabbMax, unsigned int maxHandles = 1500000, btOverlappingPairCache* pairCache = 0, bool disableRaycastAccelerator = false);
+
+};
+
+#endif
+
diff --git a/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h
new file mode 100644
index 00000000..f1bf0059
--- /dev/null
+++ b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h
@@ -0,0 +1,82 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_BROADPHASE_INTERFACE_H
+#define BT_BROADPHASE_INTERFACE_H
+
+
+
+struct btDispatcherInfo;
+class btDispatcher;
+#include "btBroadphaseProxy.h"
+
+class btOverlappingPairCache;
+
+
+
+struct btBroadphaseAabbCallback
+{
+ virtual ~btBroadphaseAabbCallback() {}
+ virtual bool process(const btBroadphaseProxy* proxy) = 0;
+};
+
+
+struct btBroadphaseRayCallback : public btBroadphaseAabbCallback
+{
+ ///added some cached data to accelerate ray-AABB tests
+ btVector3 m_rayDirectionInverse;
+ unsigned int m_signs[3];
+ btScalar m_lambda_max;
+
+ virtual ~btBroadphaseRayCallback() {}
+};
+
+#include "LinearMath/btVector3.h"
+
+///The btBroadphaseInterface class provides an interface to detect aabb-overlapping object pairs.
+///Some implementations for this broadphase interface include btAxisSweep3, bt32BitAxisSweep3 and btDbvtBroadphase.
+///The actual overlapping pair management, storage, adding and removing of pairs is dealt by the btOverlappingPairCache class.
+class btBroadphaseInterface
+{
+public:
+ virtual ~btBroadphaseInterface() {}
+
+ virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy) =0;
+ virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)=0;
+ virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher)=0;
+ virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const =0;
+
+ virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0), const btVector3& aabbMax = btVector3(0,0,0)) = 0;
+
+ virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback) = 0;
+
+ ///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb
+ virtual void calculateOverlappingPairs(btDispatcher* dispatcher)=0;
+
+ virtual btOverlappingPairCache* getOverlappingPairCache()=0;
+ virtual const btOverlappingPairCache* getOverlappingPairCache() const =0;
+
+ ///getAabb returns the axis aligned bounding box in the 'global' coordinate frame
+ ///will add some transform later
+ virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const =0;
+
+ ///reset broadphase internal structures, to ensure determinism/reproducability
+ virtual void resetPool(btDispatcher* dispatcher) { (void) dispatcher; };
+
+ virtual void printStats() = 0;
+
+};
+
+#endif //BT_BROADPHASE_INTERFACE_H
diff --git a/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp
new file mode 100644
index 00000000..f4d7341f
--- /dev/null
+++ b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp
@@ -0,0 +1,17 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btBroadphaseProxy.h"
+
diff --git a/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h
new file mode 100644
index 00000000..bb58b828
--- /dev/null
+++ b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h
@@ -0,0 +1,270 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_BROADPHASE_PROXY_H
+#define BT_BROADPHASE_PROXY_H
+
+#include "LinearMath/btScalar.h" //for SIMD_FORCE_INLINE
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btAlignedAllocator.h"
+
+
+/// btDispatcher uses these types
+/// IMPORTANT NOTE:The types are ordered polyhedral, implicit convex and concave
+/// to facilitate type checking
+/// CUSTOM_POLYHEDRAL_SHAPE_TYPE,CUSTOM_CONVEX_SHAPE_TYPE and CUSTOM_CONCAVE_SHAPE_TYPE can be used to extend Bullet without modifying source code
+enum BroadphaseNativeTypes
+{
+ // polyhedral convex shapes
+ BOX_SHAPE_PROXYTYPE,
+ TRIANGLE_SHAPE_PROXYTYPE,
+ TETRAHEDRAL_SHAPE_PROXYTYPE,
+ CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE,
+ CONVEX_HULL_SHAPE_PROXYTYPE,
+ CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE,
+ CUSTOM_POLYHEDRAL_SHAPE_TYPE,
+//implicit convex shapes
+IMPLICIT_CONVEX_SHAPES_START_HERE,
+ SPHERE_SHAPE_PROXYTYPE,
+ MULTI_SPHERE_SHAPE_PROXYTYPE,
+ CAPSULE_SHAPE_PROXYTYPE,
+ CONE_SHAPE_PROXYTYPE,
+ CONVEX_SHAPE_PROXYTYPE,
+ CYLINDER_SHAPE_PROXYTYPE,
+ UNIFORM_SCALING_SHAPE_PROXYTYPE,
+ MINKOWSKI_SUM_SHAPE_PROXYTYPE,
+ MINKOWSKI_DIFFERENCE_SHAPE_PROXYTYPE,
+ BOX_2D_SHAPE_PROXYTYPE,
+ CONVEX_2D_SHAPE_PROXYTYPE,
+ CUSTOM_CONVEX_SHAPE_TYPE,
+//concave shapes
+CONCAVE_SHAPES_START_HERE,
+ //keep all the convex shapetype below here, for the check IsConvexShape in broadphase proxy!
+ TRIANGLE_MESH_SHAPE_PROXYTYPE,
+ SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE,
+ ///used for demo integration FAST/Swift collision library and Bullet
+ FAST_CONCAVE_MESH_PROXYTYPE,
+ //terrain
+ TERRAIN_SHAPE_PROXYTYPE,
+///Used for GIMPACT Trimesh integration
+ GIMPACT_SHAPE_PROXYTYPE,
+///Multimaterial mesh
+ MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE,
+
+ EMPTY_SHAPE_PROXYTYPE,
+ STATIC_PLANE_PROXYTYPE,
+ CUSTOM_CONCAVE_SHAPE_TYPE,
+CONCAVE_SHAPES_END_HERE,
+
+ COMPOUND_SHAPE_PROXYTYPE,
+
+ SOFTBODY_SHAPE_PROXYTYPE,
+ HFFLUID_SHAPE_PROXYTYPE,
+ HFFLUID_BUOYANT_CONVEX_SHAPE_PROXYTYPE,
+ INVALID_SHAPE_PROXYTYPE,
+
+ MAX_BROADPHASE_COLLISION_TYPES
+
+};
+
+
+///The btBroadphaseProxy is the main class that can be used with the Bullet broadphases.
+///It stores collision shape type information, collision filter information and a client object, typically a btCollisionObject or btRigidBody.
+ATTRIBUTE_ALIGNED16(struct) btBroadphaseProxy
+{
+
+BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ ///optional filtering to cull potential collisions
+ enum CollisionFilterGroups
+ {
+ DefaultFilter = 1,
+ StaticFilter = 2,
+ KinematicFilter = 4,
+ DebrisFilter = 8,
+ SensorTrigger = 16,
+ CharacterFilter = 32,
+ AllFilter = -1 //all bits sets: DefaultFilter | StaticFilter | KinematicFilter | DebrisFilter | SensorTrigger
+ };
+
+ //Usually the client btCollisionObject or Rigidbody class
+ void* m_clientObject;
+ short int m_collisionFilterGroup;
+ short int m_collisionFilterMask;
+ void* m_multiSapParentProxy;
+ int m_uniqueId;//m_uniqueId is introduced for paircache. could get rid of this, by calculating the address offset etc.
+
+ btVector3 m_aabbMin;
+ btVector3 m_aabbMax;
+
+ SIMD_FORCE_INLINE int getUid() const
+ {
+ return m_uniqueId;
+ }
+
+ //used for memory pools
+ btBroadphaseProxy() :m_clientObject(0),m_multiSapParentProxy(0)
+ {
+ }
+
+ btBroadphaseProxy(const btVector3& aabbMin,const btVector3& aabbMax,void* userPtr,short int collisionFilterGroup, short int collisionFilterMask,void* multiSapParentProxy=0)
+ :m_clientObject(userPtr),
+ m_collisionFilterGroup(collisionFilterGroup),
+ m_collisionFilterMask(collisionFilterMask),
+ m_aabbMin(aabbMin),
+ m_aabbMax(aabbMax)
+ {
+ m_multiSapParentProxy = multiSapParentProxy;
+ }
+
+
+
+ static SIMD_FORCE_INLINE bool isPolyhedral(int proxyType)
+ {
+ return (proxyType < IMPLICIT_CONVEX_SHAPES_START_HERE);
+ }
+
+ static SIMD_FORCE_INLINE bool isConvex(int proxyType)
+ {
+ return (proxyType < CONCAVE_SHAPES_START_HERE);
+ }
+
+ static SIMD_FORCE_INLINE bool isNonMoving(int proxyType)
+ {
+ return (isConcave(proxyType) && !(proxyType==GIMPACT_SHAPE_PROXYTYPE));
+ }
+
+ static SIMD_FORCE_INLINE bool isConcave(int proxyType)
+ {
+ return ((proxyType > CONCAVE_SHAPES_START_HERE) &&
+ (proxyType < CONCAVE_SHAPES_END_HERE));
+ }
+ static SIMD_FORCE_INLINE bool isCompound(int proxyType)
+ {
+ return (proxyType == COMPOUND_SHAPE_PROXYTYPE);
+ }
+
+ static SIMD_FORCE_INLINE bool isSoftBody(int proxyType)
+ {
+ return (proxyType == SOFTBODY_SHAPE_PROXYTYPE);
+ }
+
+ static SIMD_FORCE_INLINE bool isInfinite(int proxyType)
+ {
+ return (proxyType == STATIC_PLANE_PROXYTYPE);
+ }
+
+ static SIMD_FORCE_INLINE bool isConvex2d(int proxyType)
+ {
+ return (proxyType == BOX_2D_SHAPE_PROXYTYPE) || (proxyType == CONVEX_2D_SHAPE_PROXYTYPE);
+ }
+
+
+}
+;
+
+class btCollisionAlgorithm;
+
+struct btBroadphaseProxy;
+
+
+
+///The btBroadphasePair class contains a pair of aabb-overlapping objects.
+///A btDispatcher can search a btCollisionAlgorithm that performs exact/narrowphase collision detection on the actual collision shapes.
+ATTRIBUTE_ALIGNED16(struct) btBroadphasePair
+{
+ btBroadphasePair ()
+ :
+ m_pProxy0(0),
+ m_pProxy1(0),
+ m_algorithm(0),
+ m_internalInfo1(0)
+ {
+ }
+
+BT_DECLARE_ALIGNED_ALLOCATOR();
+
+ btBroadphasePair(const btBroadphasePair& other)
+ : m_pProxy0(other.m_pProxy0),
+ m_pProxy1(other.m_pProxy1),
+ m_algorithm(other.m_algorithm),
+ m_internalInfo1(other.m_internalInfo1)
+ {
+ }
+ btBroadphasePair(btBroadphaseProxy& proxy0,btBroadphaseProxy& proxy1)
+ {
+
+ //keep them sorted, so the std::set operations work
+ if (proxy0.m_uniqueId < proxy1.m_uniqueId)
+ {
+ m_pProxy0 = &proxy0;
+ m_pProxy1 = &proxy1;
+ }
+ else
+ {
+ m_pProxy0 = &proxy1;
+ m_pProxy1 = &proxy0;
+ }
+
+ m_algorithm = 0;
+ m_internalInfo1 = 0;
+
+ }
+
+ btBroadphaseProxy* m_pProxy0;
+ btBroadphaseProxy* m_pProxy1;
+
+ mutable btCollisionAlgorithm* m_algorithm;
+ union { void* m_internalInfo1; int m_internalTmpValue;};//don't use this data, it will be removed in future version.
+
+};
+
+/*
+//comparison for set operation, see Solid DT_Encounter
+SIMD_FORCE_INLINE bool operator<(const btBroadphasePair& a, const btBroadphasePair& b)
+{
+ return a.m_pProxy0 < b.m_pProxy0 ||
+ (a.m_pProxy0 == b.m_pProxy0 && a.m_pProxy1 < b.m_pProxy1);
+}
+*/
+
+
+
+class btBroadphasePairSortPredicate
+{
+ public:
+
+ bool operator() ( const btBroadphasePair& a, const btBroadphasePair& b ) const
+ {
+ const int uidA0 = a.m_pProxy0 ? a.m_pProxy0->m_uniqueId : -1;
+ const int uidB0 = b.m_pProxy0 ? b.m_pProxy0->m_uniqueId : -1;
+ const int uidA1 = a.m_pProxy1 ? a.m_pProxy1->m_uniqueId : -1;
+ const int uidB1 = b.m_pProxy1 ? b.m_pProxy1->m_uniqueId : -1;
+
+ return uidA0 > uidB0 ||
+ (a.m_pProxy0 == b.m_pProxy0 && uidA1 > uidB1) ||
+ (a.m_pProxy0 == b.m_pProxy0 && a.m_pProxy1 == b.m_pProxy1 && a.m_algorithm > b.m_algorithm);
+ }
+};
+
+
+SIMD_FORCE_INLINE bool operator==(const btBroadphasePair& a, const btBroadphasePair& b)
+{
+ return (a.m_pProxy0 == b.m_pProxy0) && (a.m_pProxy1 == b.m_pProxy1);
+}
+
+
+#endif //BT_BROADPHASE_PROXY_H
+
diff --git a/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp
new file mode 100644
index 00000000..c95d1be0
--- /dev/null
+++ b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp
@@ -0,0 +1,23 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btCollisionAlgorithm.h"
+#include "btDispatcher.h"
+
+btCollisionAlgorithm::btCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
+{
+ m_dispatcher = ci.m_dispatcher1;
+}
+
diff --git a/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h
new file mode 100644
index 00000000..40565623
--- /dev/null
+++ b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h
@@ -0,0 +1,81 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_COLLISION_ALGORITHM_H
+#define BT_COLLISION_ALGORITHM_H
+
+#include "LinearMath/btScalar.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+struct btBroadphaseProxy;
+class btDispatcher;
+class btManifoldResult;
+class btCollisionObject;
+struct btCollisionObjectWrapper;
+struct btDispatcherInfo;
+class btPersistentManifold;
+
+typedef btAlignedObjectArray btManifoldArray;
+
+struct btCollisionAlgorithmConstructionInfo
+{
+ btCollisionAlgorithmConstructionInfo()
+ :m_dispatcher1(0),
+ m_manifold(0)
+ {
+ }
+ btCollisionAlgorithmConstructionInfo(btDispatcher* dispatcher,int temp)
+ :m_dispatcher1(dispatcher)
+ {
+ (void)temp;
+ }
+
+ btDispatcher* m_dispatcher1;
+ btPersistentManifold* m_manifold;
+
+// int getDispatcherId();
+
+};
+
+
+///btCollisionAlgorithm is an collision interface that is compatible with the Broadphase and btDispatcher.
+///It is persistent over frames
+class btCollisionAlgorithm
+{
+
+protected:
+
+ btDispatcher* m_dispatcher;
+
+protected:
+// int getDispatcherId();
+
+public:
+
+ btCollisionAlgorithm() {};
+
+ btCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci);
+
+ virtual ~btCollisionAlgorithm() {};
+
+ virtual void processCollision (const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) = 0;
+
+ virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) = 0;
+
+ virtual void getAllContactManifolds(btManifoldArray& manifoldArray) = 0;
+};
+
+
+#endif //BT_COLLISION_ALGORITHM_H
diff --git a/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btDbvt.cpp b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btDbvt.cpp
new file mode 100644
index 00000000..95443af5
--- /dev/null
+++ b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btDbvt.cpp
@@ -0,0 +1,1295 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+///btDbvt implementation by Nathanael Presson
+
+#include "btDbvt.h"
+
+//
+typedef btAlignedObjectArray tNodeArray;
+typedef btAlignedObjectArray tConstNodeArray;
+
+//
+struct btDbvtNodeEnumerator : btDbvt::ICollide
+{
+ tConstNodeArray nodes;
+ void Process(const btDbvtNode* n) { nodes.push_back(n); }
+};
+
+//
+static DBVT_INLINE int indexof(const btDbvtNode* node)
+{
+ return(node->parent->childs[1]==node);
+}
+
+//
+static DBVT_INLINE btDbvtVolume merge( const btDbvtVolume& a,
+ const btDbvtVolume& b)
+{
+#if (DBVT_MERGE_IMPL==DBVT_IMPL_SSE)
+ ATTRIBUTE_ALIGNED16(char locals[sizeof(btDbvtAabbMm)]);
+ btDbvtVolume& res=*(btDbvtVolume*)locals;
+#else
+ btDbvtVolume res;
+#endif
+ Merge(a,b,res);
+ return(res);
+}
+
+// volume+edge lengths
+static DBVT_INLINE btScalar size(const btDbvtVolume& a)
+{
+ const btVector3 edges=a.Lengths();
+ return( edges.x()*edges.y()*edges.z()+
+ edges.x()+edges.y()+edges.z());
+}
+
+//
+static void getmaxdepth(const btDbvtNode* node,int depth,int& maxdepth)
+{
+ if(node->isinternal())
+ {
+ getmaxdepth(node->childs[0],depth+1,maxdepth);
+ getmaxdepth(node->childs[1],depth+1,maxdepth);
+ } else maxdepth=btMax(maxdepth,depth);
+}
+
+//
+static DBVT_INLINE void deletenode( btDbvt* pdbvt,
+ btDbvtNode* node)
+{
+ btAlignedFree(pdbvt->m_free);
+ pdbvt->m_free=node;
+}
+
+//
+static void recursedeletenode( btDbvt* pdbvt,
+ btDbvtNode* node)
+{
+ if(!node->isleaf())
+ {
+ recursedeletenode(pdbvt,node->childs[0]);
+ recursedeletenode(pdbvt,node->childs[1]);
+ }
+ if(node==pdbvt->m_root) pdbvt->m_root=0;
+ deletenode(pdbvt,node);
+}
+
+//
+static DBVT_INLINE btDbvtNode* createnode( btDbvt* pdbvt,
+ btDbvtNode* parent,
+ void* data)
+{
+ btDbvtNode* node;
+ if(pdbvt->m_free)
+ { node=pdbvt->m_free;pdbvt->m_free=0; }
+ else
+ { node=new(btAlignedAlloc(sizeof(btDbvtNode),16)) btDbvtNode(); }
+ node->parent = parent;
+ node->data = data;
+ node->childs[1] = 0;
+ return(node);
+}
+
+//
+static DBVT_INLINE btDbvtNode* createnode( btDbvt* pdbvt,
+ btDbvtNode* parent,
+ const btDbvtVolume& volume,
+ void* data)
+{
+ btDbvtNode* node=createnode(pdbvt,parent,data);
+ node->volume=volume;
+ return(node);
+}
+
+//
+static DBVT_INLINE btDbvtNode* createnode( btDbvt* pdbvt,
+ btDbvtNode* parent,
+ const btDbvtVolume& volume0,
+ const btDbvtVolume& volume1,
+ void* data)
+{
+ btDbvtNode* node=createnode(pdbvt,parent,data);
+ Merge(volume0,volume1,node->volume);
+ return(node);
+}
+
+//
+static void insertleaf( btDbvt* pdbvt,
+ btDbvtNode* root,
+ btDbvtNode* leaf)
+{
+ if(!pdbvt->m_root)
+ {
+ pdbvt->m_root = leaf;
+ leaf->parent = 0;
+ }
+ else
+ {
+ if(!root->isleaf())
+ {
+ do {
+ root=root->childs[Select( leaf->volume,
+ root->childs[0]->volume,
+ root->childs[1]->volume)];
+ } while(!root->isleaf());
+ }
+ btDbvtNode* prev=root->parent;
+ btDbvtNode* node=createnode(pdbvt,prev,leaf->volume,root->volume,0);
+ if(prev)
+ {
+ prev->childs[indexof(root)] = node;
+ node->childs[0] = root;root->parent=node;
+ node->childs[1] = leaf;leaf->parent=node;
+ do {
+ if(!prev->volume.Contain(node->volume))
+ Merge(prev->childs[0]->volume,prev->childs[1]->volume,prev->volume);
+ else
+ break;
+ node=prev;
+ } while(0!=(prev=node->parent));
+ }
+ else
+ {
+ node->childs[0] = root;root->parent=node;
+ node->childs[1] = leaf;leaf->parent=node;
+ pdbvt->m_root = node;
+ }
+ }
+}
+
+//
+static btDbvtNode* removeleaf( btDbvt* pdbvt,
+ btDbvtNode* leaf)
+{
+ if(leaf==pdbvt->m_root)
+ {
+ pdbvt->m_root=0;
+ return(0);
+ }
+ else
+ {
+ btDbvtNode* parent=leaf->parent;
+ btDbvtNode* prev=parent->parent;
+ btDbvtNode* sibling=parent->childs[1-indexof(leaf)];
+ if(prev)
+ {
+ prev->childs[indexof(parent)]=sibling;
+ sibling->parent=prev;
+ deletenode(pdbvt,parent);
+ while(prev)
+ {
+ const btDbvtVolume pb=prev->volume;
+ Merge(prev->childs[0]->volume,prev->childs[1]->volume,prev->volume);
+ if(NotEqual(pb,prev->volume))
+ {
+ prev=prev->parent;
+ } else break;
+ }
+ return(prev?prev:pdbvt->m_root);
+ }
+ else
+ {
+ pdbvt->m_root=sibling;
+ sibling->parent=0;
+ deletenode(pdbvt,parent);
+ return(pdbvt->m_root);
+ }
+ }
+}
+
+//
+static void fetchleaves(btDbvt* pdbvt,
+ btDbvtNode* root,
+ tNodeArray& leaves,
+ int depth=-1)
+{
+ if(root->isinternal()&&depth)
+ {
+ fetchleaves(pdbvt,root->childs[0],leaves,depth-1);
+ fetchleaves(pdbvt,root->childs[1],leaves,depth-1);
+ deletenode(pdbvt,root);
+ }
+ else
+ {
+ leaves.push_back(root);
+ }
+}
+
+//
+static void split( const tNodeArray& leaves,
+ tNodeArray& left,
+ tNodeArray& right,
+ const btVector3& org,
+ const btVector3& axis)
+{
+ left.resize(0);
+ right.resize(0);
+ for(int i=0,ni=leaves.size();ivolume.Center()-org)<0)
+ left.push_back(leaves[i]);
+ else
+ right.push_back(leaves[i]);
+ }
+}
+
+//
+static btDbvtVolume bounds( const tNodeArray& leaves)
+{
+#if DBVT_MERGE_IMPL==DBVT_IMPL_SSE
+ ATTRIBUTE_ALIGNED16(char locals[sizeof(btDbvtVolume)]);
+ btDbvtVolume& volume=*(btDbvtVolume*)locals;
+ volume=leaves[0]->volume;
+#else
+ btDbvtVolume volume=leaves[0]->volume;
+#endif
+ for(int i=1,ni=leaves.size();ivolume,volume);
+ }
+ return(volume);
+}
+
+//
+static void bottomup( btDbvt* pdbvt,
+ tNodeArray& leaves)
+{
+ while(leaves.size()>1)
+ {
+ btScalar minsize=SIMD_INFINITY;
+ int minidx[2]={-1,-1};
+ for(int i=0;ivolume,leaves[j]->volume));
+ if(szvolume,n[1]->volume,0);
+ p->childs[0] = n[0];
+ p->childs[1] = n[1];
+ n[0]->parent = p;
+ n[1]->parent = p;
+ leaves[minidx[0]] = p;
+ leaves.swap(minidx[1],leaves.size()-1);
+ leaves.pop_back();
+ }
+}
+
+//
+static btDbvtNode* topdown(btDbvt* pdbvt,
+ tNodeArray& leaves,
+ int bu_treshold)
+{
+ static const btVector3 axis[]={btVector3(1,0,0),
+ btVector3(0,1,0),
+ btVector3(0,0,1)};
+ if(leaves.size()>1)
+ {
+ if(leaves.size()>bu_treshold)
+ {
+ const btDbvtVolume vol=bounds(leaves);
+ const btVector3 org=vol.Center();
+ tNodeArray sets[2];
+ int bestaxis=-1;
+ int bestmidp=leaves.size();
+ int splitcount[3][2]={{0,0},{0,0},{0,0}};
+ int i;
+ for( i=0;ivolume.Center()-org;
+ for(int j=0;j<3;++j)
+ {
+ ++splitcount[j][btDot(x,axis[j])>0?1:0];
+ }
+ }
+ for( i=0;i<3;++i)
+ {
+ if((splitcount[i][0]>0)&&(splitcount[i][1]>0))
+ {
+ const int midp=(int)btFabs(btScalar(splitcount[i][0]-splitcount[i][1]));
+ if(midp=0)
+ {
+ sets[0].reserve(splitcount[bestaxis][0]);
+ sets[1].reserve(splitcount[bestaxis][1]);
+ split(leaves,sets[0],sets[1],org,axis[bestaxis]);
+ }
+ else
+ {
+ sets[0].reserve(leaves.size()/2+1);
+ sets[1].reserve(leaves.size()/2);
+ for(int i=0,ni=leaves.size();ichilds[0]=topdown(pdbvt,sets[0],bu_treshold);
+ node->childs[1]=topdown(pdbvt,sets[1],bu_treshold);
+ node->childs[0]->parent=node;
+ node->childs[1]->parent=node;
+ return(node);
+ }
+ else
+ {
+ bottomup(pdbvt,leaves);
+ return(leaves[0]);
+ }
+ }
+ return(leaves[0]);
+}
+
+//
+static DBVT_INLINE btDbvtNode* sort(btDbvtNode* n,btDbvtNode*& r)
+{
+ btDbvtNode* p=n->parent;
+ btAssert(n->isinternal());
+ if(p>n)
+ {
+ const int i=indexof(n);
+ const int j=1-i;
+ btDbvtNode* s=p->childs[j];
+ btDbvtNode* q=p->parent;
+ btAssert(n==p->childs[i]);
+ if(q) q->childs[indexof(p)]=n; else r=n;
+ s->parent=n;
+ p->parent=n;
+ n->parent=q;
+ p->childs[0]=n->childs[0];
+ p->childs[1]=n->childs[1];
+ n->childs[0]->parent=p;
+ n->childs[1]->parent=p;
+ n->childs[i]=p;
+ n->childs[j]=s;
+ btSwap(p->volume,n->volume);
+ return(p);
+ }
+ return(n);
+}
+
+#if 0
+static DBVT_INLINE btDbvtNode* walkup(btDbvtNode* n,int count)
+{
+ while(n&&(count--)) n=n->parent;
+ return(n);
+}
+#endif
+
+//
+// Api
+//
+
+//
+btDbvt::btDbvt()
+{
+ m_root = 0;
+ m_free = 0;
+ m_lkhd = -1;
+ m_leaves = 0;
+ m_opath = 0;
+}
+
+//
+btDbvt::~btDbvt()
+{
+ clear();
+}
+
+//
+void btDbvt::clear()
+{
+ if(m_root)
+ recursedeletenode(this,m_root);
+ btAlignedFree(m_free);
+ m_free=0;
+ m_lkhd = -1;
+ m_stkStack.clear();
+ m_opath = 0;
+
+}
+
+//
+void btDbvt::optimizeBottomUp()
+{
+ if(m_root)
+ {
+ tNodeArray leaves;
+ leaves.reserve(m_leaves);
+ fetchleaves(this,m_root,leaves);
+ bottomup(this,leaves);
+ m_root=leaves[0];
+ }
+}
+
+//
+void btDbvt::optimizeTopDown(int bu_treshold)
+{
+ if(m_root)
+ {
+ tNodeArray leaves;
+ leaves.reserve(m_leaves);
+ fetchleaves(this,m_root,leaves);
+ m_root=topdown(this,leaves,bu_treshold);
+ }
+}
+
+//
+void btDbvt::optimizeIncremental(int passes)
+{
+ if(passes<0) passes=m_leaves;
+ if(m_root&&(passes>0))
+ {
+ do {
+ btDbvtNode* node=m_root;
+ unsigned bit=0;
+ while(node->isinternal())
+ {
+ node=sort(node,m_root)->childs[(m_opath>>bit)&1];
+ bit=(bit+1)&(sizeof(unsigned)*8-1);
+ }
+ update(node);
+ ++m_opath;
+ } while(--passes);
+ }
+}
+
+//
+btDbvtNode* btDbvt::insert(const btDbvtVolume& volume,void* data)
+{
+ btDbvtNode* leaf=createnode(this,0,volume,data);
+ insertleaf(this,m_root,leaf);
+ ++m_leaves;
+ return(leaf);
+}
+
+//
+void btDbvt::update(btDbvtNode* leaf,int lookahead)
+{
+ btDbvtNode* root=removeleaf(this,leaf);
+ if(root)
+ {
+ if(lookahead>=0)
+ {
+ for(int i=0;(iparent;++i)
+ {
+ root=root->parent;
+ }
+ } else root=m_root;
+ }
+ insertleaf(this,root,leaf);
+}
+
+//
+void btDbvt::update(btDbvtNode* leaf,btDbvtVolume& volume)
+{
+ btDbvtNode* root=removeleaf(this,leaf);
+ if(root)
+ {
+ if(m_lkhd>=0)
+ {
+ for(int i=0;(iparent;++i)
+ {
+ root=root->parent;
+ }
+ } else root=m_root;
+ }
+ leaf->volume=volume;
+ insertleaf(this,root,leaf);
+}
+
+//
+bool btDbvt::update(btDbvtNode* leaf,btDbvtVolume& volume,const btVector3& velocity,btScalar margin)
+{
+ if(leaf->volume.Contain(volume)) return(false);
+ volume.Expand(btVector3(margin,margin,margin));
+ volume.SignedExpand(velocity);
+ update(leaf,volume);
+ return(true);
+}
+
+//
+bool btDbvt::update(btDbvtNode* leaf,btDbvtVolume& volume,const btVector3& velocity)
+{
+ if(leaf->volume.Contain(volume)) return(false);
+ volume.SignedExpand(velocity);
+ update(leaf,volume);
+ return(true);
+}
+
+//
+bool btDbvt::update(btDbvtNode* leaf,btDbvtVolume& volume,btScalar margin)
+{
+ if(leaf->volume.Contain(volume)) return(false);
+ volume.Expand(btVector3(margin,margin,margin));
+ update(leaf,volume);
+ return(true);
+}
+
+//
+void btDbvt::remove(btDbvtNode* leaf)
+{
+ removeleaf(this,leaf);
+ deletenode(this,leaf);
+ --m_leaves;
+}
+
+//
+void btDbvt::write(IWriter* iwriter) const
+{
+ btDbvtNodeEnumerator nodes;
+ nodes.nodes.reserve(m_leaves*2);
+ enumNodes(m_root,nodes);
+ iwriter->Prepare(m_root,nodes.nodes.size());
+ for(int i=0;iparent) p=nodes.nodes.findLinearSearch(n->parent);
+ if(n->isinternal())
+ {
+ const int c0=nodes.nodes.findLinearSearch(n->childs[0]);
+ const int c1=nodes.nodes.findLinearSearch(n->childs[1]);
+ iwriter->WriteNode(n,i,p,c0,c1);
+ }
+ else
+ {
+ iwriter->WriteLeaf(n,i,p);
+ }
+ }
+}
+
+//
+void btDbvt::clone(btDbvt& dest,IClone* iclone) const
+{
+ dest.clear();
+ if(m_root!=0)
+ {
+ btAlignedObjectArray stack;
+ stack.reserve(m_leaves);
+ stack.push_back(sStkCLN(m_root,0));
+ do {
+ const int i=stack.size()-1;
+ const sStkCLN e=stack[i];
+ btDbvtNode* n=createnode(&dest,e.parent,e.node->volume,e.node->data);
+ stack.pop_back();
+ if(e.parent!=0)
+ e.parent->childs[i&1]=n;
+ else
+ dest.m_root=n;
+ if(e.node->isinternal())
+ {
+ stack.push_back(sStkCLN(e.node->childs[0],n));
+ stack.push_back(sStkCLN(e.node->childs[1],n));
+ }
+ else
+ {
+ iclone->CloneLeaf(n);
+ }
+ } while(stack.size()>0);
+ }
+}
+
+//
+int btDbvt::maxdepth(const btDbvtNode* node)
+{
+ int depth=0;
+ if(node) getmaxdepth(node,1,depth);
+ return(depth);
+}
+
+//
+int btDbvt::countLeaves(const btDbvtNode* node)
+{
+ if(node->isinternal())
+ return(countLeaves(node->childs[0])+countLeaves(node->childs[1]));
+ else
+ return(1);
+}
+
+//
+void btDbvt::extractLeaves(const btDbvtNode* node,btAlignedObjectArray& leaves)
+{
+ if(node->isinternal())
+ {
+ extractLeaves(node->childs[0],leaves);
+ extractLeaves(node->childs[1],leaves);
+ }
+ else
+ {
+ leaves.push_back(node);
+ }
+}
+
+//
+#if DBVT_ENABLE_BENCHMARK
+
+#include
+#include
+#include "LinearMath/btQuickProf.h"
+
+/*
+q6600,2.4ghz
+
+/Ox /Ob2 /Oi /Ot /I "." /I "..\.." /I "..\..\src" /D "NDEBUG" /D "_LIB" /D "_WINDOWS" /D "_CRT_SECURE_NO_DEPRECATE" /D "_CRT_NONSTDC_NO_DEPRECATE" /D "WIN32"
+/GF /FD /MT /GS- /Gy /arch:SSE2 /Zc:wchar_t- /Fp"..\..\out\release8\build\libbulletcollision\libbulletcollision.pch"
+/Fo"..\..\out\release8\build\libbulletcollision\\"
+/Fd"..\..\out\release8\build\libbulletcollision\bulletcollision.pdb"
+/W3 /nologo /c /Wp64 /Zi /errorReport:prompt
+
+Benchmarking dbvt...
+World scale: 100.000000
+Extents base: 1.000000
+Extents range: 4.000000
+Leaves: 8192
+sizeof(btDbvtVolume): 32 bytes
+sizeof(btDbvtNode): 44 bytes
+[1] btDbvtVolume intersections: 3499 ms (-1%)
+[2] btDbvtVolume merges: 1934 ms (0%)
+[3] btDbvt::collideTT: 5485 ms (-21%)
+[4] btDbvt::collideTT self: 2814 ms (-20%)
+[5] btDbvt::collideTT xform: 7379 ms (-1%)
+[6] btDbvt::collideTT xform,self: 7270 ms (-2%)
+[7] btDbvt::rayTest: 6314 ms (0%),(332143 r/s)
+[8] insert/remove: 2093 ms (0%),(1001983 ir/s)
+[9] updates (teleport): 1879 ms (-3%),(1116100 u/s)
+[10] updates (jitter): 1244 ms (-4%),(1685813 u/s)
+[11] optimize (incremental): 2514 ms (0%),(1668000 o/s)
+[12] btDbvtVolume notequal: 3659 ms (0%)
+[13] culling(OCL+fullsort): 2218 ms (0%),(461 t/s)
+[14] culling(OCL+qsort): 3688 ms (5%),(2221 t/s)
+[15] culling(KDOP+qsort): 1139 ms (-1%),(7192 t/s)
+[16] insert/remove batch(256): 5092 ms (0%),(823704 bir/s)
+[17] btDbvtVolume select: 3419 ms (0%)
+*/
+
+struct btDbvtBenchmark
+{
+ struct NilPolicy : btDbvt::ICollide
+ {
+ NilPolicy() : m_pcount(0),m_depth(-SIMD_INFINITY),m_checksort(true) {}
+ void Process(const btDbvtNode*,const btDbvtNode*) { ++m_pcount; }
+ void Process(const btDbvtNode*) { ++m_pcount; }
+ void Process(const btDbvtNode*,btScalar depth)
+ {
+ ++m_pcount;
+ if(m_checksort)
+ { if(depth>=m_depth) m_depth=depth; else printf("wrong depth: %f (should be >= %f)\r\n",depth,m_depth); }
+ }
+ int m_pcount;
+ btScalar m_depth;
+ bool m_checksort;
+ };
+ struct P14 : btDbvt::ICollide
+ {
+ struct Node
+ {
+ const btDbvtNode* leaf;
+ btScalar depth;
+ };
+ void Process(const btDbvtNode* leaf,btScalar depth)
+ {
+ Node n;
+ n.leaf = leaf;
+ n.depth = depth;
+ }
+ static int sortfnc(const Node& a,const Node& b)
+ {
+ if(a.depthb.depth) return(-1);
+ return(0);
+ }
+ btAlignedObjectArray m_nodes;
+ };
+ struct P15 : btDbvt::ICollide
+ {
+ struct Node
+ {
+ const btDbvtNode* leaf;
+ btScalar depth;
+ };
+ void Process(const btDbvtNode* leaf)
+ {
+ Node n;
+ n.leaf = leaf;
+ n.depth = dot(leaf->volume.Center(),m_axis);
+ }
+ static int sortfnc(const Node& a,const Node& b)
+ {
+ if(a.depthb.depth) return(-1);
+ return(0);
+ }
+ btAlignedObjectArray m_nodes;
+ btVector3 m_axis;
+ };
+ static btScalar RandUnit()
+ {
+ return(rand()/(btScalar)RAND_MAX);
+ }
+ static btVector3 RandVector3()
+ {
+ return(btVector3(RandUnit(),RandUnit(),RandUnit()));
+ }
+ static btVector3 RandVector3(btScalar cs)
+ {
+ return(RandVector3()*cs-btVector3(cs,cs,cs)/2);
+ }
+ static btDbvtVolume RandVolume(btScalar cs,btScalar eb,btScalar es)
+ {
+ return(btDbvtVolume::FromCE(RandVector3(cs),btVector3(eb,eb,eb)+RandVector3()*es));
+ }
+ static btTransform RandTransform(btScalar cs)
+ {
+ btTransform t;
+ t.setOrigin(RandVector3(cs));
+ t.setRotation(btQuaternion(RandUnit()*SIMD_PI*2,RandUnit()*SIMD_PI*2,RandUnit()*SIMD_PI*2).normalized());
+ return(t);
+ }
+ static void RandTree(btScalar cs,btScalar eb,btScalar es,int leaves,btDbvt& dbvt)
+ {
+ dbvt.clear();
+ for(int i=0;i volumes;
+ btAlignedObjectArray results;
+ volumes.resize(cfgLeaves);
+ results.resize(cfgLeaves);
+ for(int i=0;i volumes;
+ btAlignedObjectArray results;
+ volumes.resize(cfgLeaves);
+ results.resize(cfgLeaves);
+ for(int i=0;i transforms;
+ btDbvtBenchmark::NilPolicy policy;
+ transforms.resize(cfgBenchmark5_Iterations);
+ for(int i=0;i transforms;
+ btDbvtBenchmark::NilPolicy policy;
+ transforms.resize(cfgBenchmark6_Iterations);
+ for(int i=0;i rayorg;
+ btAlignedObjectArray raydir;
+ btDbvtBenchmark::NilPolicy policy;
+ rayorg.resize(cfgBenchmark7_Iterations);
+ raydir.resize(cfgBenchmark7_Iterations);
+ for(int i=0;i leaves;
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ dbvt.optimizeTopDown();
+ dbvt.extractLeaves(dbvt.m_root,leaves);
+ printf("[9] updates (teleport): ");
+ wallclock.reset();
+ for(int i=0;i(leaves[rand()%cfgLeaves]),
+ btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale));
+ }
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ const int up=cfgBenchmark9_Passes*cfgBenchmark9_Iterations;
+ printf("%u ms (%i%%),(%u u/s)\r\n",time,(time-cfgBenchmark9_Reference)*100/time,up*1000/time);
+ }
+ if(cfgBenchmark10_Enable)
+ {// Benchmark 10
+ srand(380843);
+ btDbvt dbvt;
+ btAlignedObjectArray leaves;
+ btAlignedObjectArray vectors;
+ vectors.resize(cfgBenchmark10_Iterations);
+ for(int i=0;i(leaves[rand()%cfgLeaves]);
+ btDbvtVolume v=btDbvtVolume::FromMM(l->volume.Mins()+d,l->volume.Maxs()+d);
+ dbvt.update(l,v);
+ }
+ }
+ const int time=(int)wallclock.getTimeMilliseconds();
+ const int up=cfgBenchmark10_Passes*cfgBenchmark10_Iterations;
+ printf("%u ms (%i%%),(%u u/s)\r\n",time,(time-cfgBenchmark10_Reference)*100/time,up*1000/time);
+ }
+ if(cfgBenchmark11_Enable)
+ {// Benchmark 11
+ srand(380843);
+ btDbvt dbvt;
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ dbvt.optimizeTopDown();
+ printf("[11] optimize (incremental): ");
+ wallclock.reset();
+ for(int i=0;i volumes;
+ btAlignedObjectArray results;
+ volumes.resize(cfgLeaves);
+ results.resize(cfgLeaves);
+ for(int i=0;i vectors;
+ btDbvtBenchmark::NilPolicy policy;
+ vectors.resize(cfgBenchmark13_Iterations);
+ for(int i=0;i vectors;
+ btDbvtBenchmark::P14 policy;
+ vectors.resize(cfgBenchmark14_Iterations);
+ for(int i=0;i vectors;
+ btDbvtBenchmark::P15 policy;
+ vectors.resize(cfgBenchmark15_Iterations);
+ for(int i=0;i batch;
+ btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+ dbvt.optimizeTopDown();
+ batch.reserve(cfgBenchmark16_BatchCount);
+ printf("[16] insert/remove batch(%u): ",cfgBenchmark16_BatchCount);
+ wallclock.reset();
+ for(int i=0;i volumes;
+ btAlignedObjectArray results;
+ btAlignedObjectArray indices;
+ volumes.resize(cfgLeaves);
+ results.resize(cfgLeaves);
+ indices.resize(cfgLeaves);
+ for(int i=0;i= 1400)
+#define DBVT_USE_TEMPLATE 1
+#else
+#define DBVT_USE_TEMPLATE 0
+#endif
+#else
+#define DBVT_USE_TEMPLATE 0
+#endif
+
+// Use only intrinsics instead of inline asm
+#define DBVT_USE_INTRINSIC_SSE 1
+
+// Using memmov for collideOCL
+#define DBVT_USE_MEMMOVE 1
+
+// Enable benchmarking code
+#define DBVT_ENABLE_BENCHMARK 0
+
+// Inlining
+#define DBVT_INLINE SIMD_FORCE_INLINE
+
+// Specific methods implementation
+
+//SSE gives errors on a MSVC 7.1
+#if defined (BT_USE_SSE) //&& defined (_WIN32)
+#define DBVT_SELECT_IMPL DBVT_IMPL_SSE
+#define DBVT_MERGE_IMPL DBVT_IMPL_SSE
+#define DBVT_INT0_IMPL DBVT_IMPL_SSE
+#else
+#define DBVT_SELECT_IMPL DBVT_IMPL_GENERIC
+#define DBVT_MERGE_IMPL DBVT_IMPL_GENERIC
+#define DBVT_INT0_IMPL DBVT_IMPL_GENERIC
+#endif
+
+#if (DBVT_SELECT_IMPL==DBVT_IMPL_SSE)|| \
+ (DBVT_MERGE_IMPL==DBVT_IMPL_SSE)|| \
+ (DBVT_INT0_IMPL==DBVT_IMPL_SSE)
+#include
+#endif
+
+//
+// Auto config and checks
+//
+
+#if DBVT_USE_TEMPLATE
+#define DBVT_VIRTUAL
+#define DBVT_VIRTUAL_DTOR(a)
+#define DBVT_PREFIX template
+#define DBVT_IPOLICY T& policy
+#define DBVT_CHECKTYPE static const ICollide& typechecker=*(T*)1;(void)typechecker;
+#else
+#define DBVT_VIRTUAL_DTOR(a) virtual ~a() {}
+#define DBVT_VIRTUAL virtual
+#define DBVT_PREFIX
+#define DBVT_IPOLICY ICollide& policy
+#define DBVT_CHECKTYPE
+#endif
+
+#if DBVT_USE_MEMMOVE
+#if !defined( __CELLOS_LV2__) && !defined(__MWERKS__)
+#include
+#endif
+#include
+#endif
+
+#ifndef DBVT_USE_TEMPLATE
+#error "DBVT_USE_TEMPLATE undefined"
+#endif
+
+#ifndef DBVT_USE_MEMMOVE
+#error "DBVT_USE_MEMMOVE undefined"
+#endif
+
+#ifndef DBVT_ENABLE_BENCHMARK
+#error "DBVT_ENABLE_BENCHMARK undefined"
+#endif
+
+#ifndef DBVT_SELECT_IMPL
+#error "DBVT_SELECT_IMPL undefined"
+#endif
+
+#ifndef DBVT_MERGE_IMPL
+#error "DBVT_MERGE_IMPL undefined"
+#endif
+
+#ifndef DBVT_INT0_IMPL
+#error "DBVT_INT0_IMPL undefined"
+#endif
+
+//
+// Defaults volumes
+//
+
+/* btDbvtAabbMm */
+struct btDbvtAabbMm
+{
+ DBVT_INLINE btVector3 Center() const { return((mi+mx)/2); }
+ DBVT_INLINE btVector3 Lengths() const { return(mx-mi); }
+ DBVT_INLINE btVector3 Extents() const { return((mx-mi)/2); }
+ DBVT_INLINE const btVector3& Mins() const { return(mi); }
+ DBVT_INLINE const btVector3& Maxs() const { return(mx); }
+ static inline btDbvtAabbMm FromCE(const btVector3& c,const btVector3& e);
+ static inline btDbvtAabbMm FromCR(const btVector3& c,btScalar r);
+ static inline btDbvtAabbMm FromMM(const btVector3& mi,const btVector3& mx);
+ static inline btDbvtAabbMm FromPoints(const btVector3* pts,int n);
+ static inline btDbvtAabbMm FromPoints(const btVector3** ppts,int n);
+ DBVT_INLINE void Expand(const btVector3& e);
+ DBVT_INLINE void SignedExpand(const btVector3& e);
+ DBVT_INLINE bool Contain(const btDbvtAabbMm& a) const;
+ DBVT_INLINE int Classify(const btVector3& n,btScalar o,int s) const;
+ DBVT_INLINE btScalar ProjectMinimum(const btVector3& v,unsigned signs) const;
+ DBVT_INLINE friend bool Intersect( const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b);
+
+ DBVT_INLINE friend bool Intersect( const btDbvtAabbMm& a,
+ const btVector3& b);
+
+ DBVT_INLINE friend btScalar Proximity( const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b);
+ DBVT_INLINE friend int Select( const btDbvtAabbMm& o,
+ const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b);
+ DBVT_INLINE friend void Merge( const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b,
+ btDbvtAabbMm& r);
+ DBVT_INLINE friend bool NotEqual( const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b);
+
+ DBVT_INLINE btVector3& tMins() { return(mi); }
+ DBVT_INLINE btVector3& tMaxs() { return(mx); }
+
+private:
+ DBVT_INLINE void AddSpan(const btVector3& d,btScalar& smi,btScalar& smx) const;
+private:
+ btVector3 mi,mx;
+};
+
+// Types
+typedef btDbvtAabbMm btDbvtVolume;
+
+/* btDbvtNode */
+struct btDbvtNode
+{
+ btDbvtVolume volume;
+ btDbvtNode* parent;
+ DBVT_INLINE bool isleaf() const { return(childs[1]==0); }
+ DBVT_INLINE bool isinternal() const { return(!isleaf()); }
+ union
+ {
+ btDbvtNode* childs[2];
+ void* data;
+ int dataAsInt;
+ };
+};
+
+///The btDbvt class implements a fast dynamic bounding volume tree based on axis aligned bounding boxes (aabb tree).
+///This btDbvt is used for soft body collision detection and for the btDbvtBroadphase. It has a fast insert, remove and update of nodes.
+///Unlike the btQuantizedBvh, nodes can be dynamically moved around, which allows for change in topology of the underlying data structure.
+struct btDbvt
+{
+ /* Stack element */
+ struct sStkNN
+ {
+ const btDbvtNode* a;
+ const btDbvtNode* b;
+ sStkNN() {}
+ sStkNN(const btDbvtNode* na,const btDbvtNode* nb) : a(na),b(nb) {}
+ };
+ struct sStkNP
+ {
+ const btDbvtNode* node;
+ int mask;
+ sStkNP(const btDbvtNode* n,unsigned m) : node(n),mask(m) {}
+ };
+ struct sStkNPS
+ {
+ const btDbvtNode* node;
+ int mask;
+ btScalar value;
+ sStkNPS() {}
+ sStkNPS(const btDbvtNode* n,unsigned m,btScalar v) : node(n),mask(m),value(v) {}
+ };
+ struct sStkCLN
+ {
+ const btDbvtNode* node;
+ btDbvtNode* parent;
+ sStkCLN(const btDbvtNode* n,btDbvtNode* p) : node(n),parent(p) {}
+ };
+ // Policies/Interfaces
+
+ /* ICollide */
+ struct ICollide
+ {
+ DBVT_VIRTUAL_DTOR(ICollide)
+ DBVT_VIRTUAL void Process(const btDbvtNode*,const btDbvtNode*) {}
+ DBVT_VIRTUAL void Process(const btDbvtNode*) {}
+ DBVT_VIRTUAL void Process(const btDbvtNode* n,btScalar) { Process(n); }
+ DBVT_VIRTUAL bool Descent(const btDbvtNode*) { return(true); }
+ DBVT_VIRTUAL bool AllLeaves(const btDbvtNode*) { return(true); }
+ };
+ /* IWriter */
+ struct IWriter
+ {
+ virtual ~IWriter() {}
+ virtual void Prepare(const btDbvtNode* root,int numnodes)=0;
+ virtual void WriteNode(const btDbvtNode*,int index,int parent,int child0,int child1)=0;
+ virtual void WriteLeaf(const btDbvtNode*,int index,int parent)=0;
+ };
+ /* IClone */
+ struct IClone
+ {
+ virtual ~IClone() {}
+ virtual void CloneLeaf(btDbvtNode*) {}
+ };
+
+ // Constants
+ enum {
+ SIMPLE_STACKSIZE = 64,
+ DOUBLE_STACKSIZE = SIMPLE_STACKSIZE*2
+ };
+
+ // Fields
+ btDbvtNode* m_root;
+ btDbvtNode* m_free;
+ int m_lkhd;
+ int m_leaves;
+ unsigned m_opath;
+
+
+ btAlignedObjectArray m_stkStack;
+ mutable btAlignedObjectArray m_rayTestStack;
+
+
+ // Methods
+ btDbvt();
+ ~btDbvt();
+ void clear();
+ bool empty() const { return(0==m_root); }
+ void optimizeBottomUp();
+ void optimizeTopDown(int bu_treshold=128);
+ void optimizeIncremental(int passes);
+ btDbvtNode* insert(const btDbvtVolume& box,void* data);
+ void update(btDbvtNode* leaf,int lookahead=-1);
+ void update(btDbvtNode* leaf,btDbvtVolume& volume);
+ bool update(btDbvtNode* leaf,btDbvtVolume& volume,const btVector3& velocity,btScalar margin);
+ bool update(btDbvtNode* leaf,btDbvtVolume& volume,const btVector3& velocity);
+ bool update(btDbvtNode* leaf,btDbvtVolume& volume,btScalar margin);
+ void remove(btDbvtNode* leaf);
+ void write(IWriter* iwriter) const;
+ void clone(btDbvt& dest,IClone* iclone=0) const;
+ static int maxdepth(const btDbvtNode* node);
+ static int countLeaves(const btDbvtNode* node);
+ static void extractLeaves(const btDbvtNode* node,btAlignedObjectArray& leaves);
+#if DBVT_ENABLE_BENCHMARK
+ static void benchmark();
+#else
+ static void benchmark(){}
+#endif
+ // DBVT_IPOLICY must support ICollide policy/interface
+ DBVT_PREFIX
+ static void enumNodes( const btDbvtNode* root,
+ DBVT_IPOLICY);
+ DBVT_PREFIX
+ static void enumLeaves( const btDbvtNode* root,
+ DBVT_IPOLICY);
+ DBVT_PREFIX
+ void collideTT( const btDbvtNode* root0,
+ const btDbvtNode* root1,
+ DBVT_IPOLICY);
+
+ DBVT_PREFIX
+ void collideTTpersistentStack( const btDbvtNode* root0,
+ const btDbvtNode* root1,
+ DBVT_IPOLICY);
+#if 0
+ DBVT_PREFIX
+ void collideTT( const btDbvtNode* root0,
+ const btDbvtNode* root1,
+ const btTransform& xform,
+ DBVT_IPOLICY);
+ DBVT_PREFIX
+ void collideTT( const btDbvtNode* root0,
+ const btTransform& xform0,
+ const btDbvtNode* root1,
+ const btTransform& xform1,
+ DBVT_IPOLICY);
+#endif
+
+ DBVT_PREFIX
+ void collideTV( const btDbvtNode* root,
+ const btDbvtVolume& volume,
+ DBVT_IPOLICY) const;
+ ///rayTest is a re-entrant ray test, and can be called in parallel as long as the btAlignedAlloc is thread-safe (uses locking etc)
+ ///rayTest is slower than rayTestInternal, because it builds a local stack, using memory allocations, and it recomputes signs/rayDirectionInverses each time
+ DBVT_PREFIX
+ static void rayTest( const btDbvtNode* root,
+ const btVector3& rayFrom,
+ const btVector3& rayTo,
+ DBVT_IPOLICY);
+ ///rayTestInternal is faster than rayTest, because it uses a persistent stack (to reduce dynamic memory allocations to a minimum) and it uses precomputed signs/rayInverseDirections
+ ///rayTestInternal is used by btDbvtBroadphase to accelerate world ray casts
+ DBVT_PREFIX
+ void rayTestInternal( const btDbvtNode* root,
+ const btVector3& rayFrom,
+ const btVector3& rayTo,
+ const btVector3& rayDirectionInverse,
+ unsigned int signs[3],
+ btScalar lambda_max,
+ const btVector3& aabbMin,
+ const btVector3& aabbMax,
+ DBVT_IPOLICY) const;
+
+ DBVT_PREFIX
+ static void collideKDOP(const btDbvtNode* root,
+ const btVector3* normals,
+ const btScalar* offsets,
+ int count,
+ DBVT_IPOLICY);
+ DBVT_PREFIX
+ static void collideOCL( const btDbvtNode* root,
+ const btVector3* normals,
+ const btScalar* offsets,
+ const btVector3& sortaxis,
+ int count,
+ DBVT_IPOLICY,
+ bool fullsort=true);
+ DBVT_PREFIX
+ static void collideTU( const btDbvtNode* root,
+ DBVT_IPOLICY);
+ // Helpers
+ static DBVT_INLINE int nearest(const int* i,const btDbvt::sStkNPS* a,btScalar v,int l,int h)
+ {
+ int m=0;
+ while(l>1;
+ if(a[i[m]].value>=v) l=m+1; else h=m;
+ }
+ return(h);
+ }
+ static DBVT_INLINE int allocate( btAlignedObjectArray& ifree,
+ btAlignedObjectArray& stock,
+ const sStkNPS& value)
+ {
+ int i;
+ if(ifree.size()>0)
+ { i=ifree[ifree.size()-1];ifree.pop_back();stock[i]=value; }
+ else
+ { i=stock.size();stock.push_back(value); }
+ return(i);
+ }
+ //
+private:
+ btDbvt(const btDbvt&) {}
+};
+
+//
+// Inline's
+//
+
+//
+inline btDbvtAabbMm btDbvtAabbMm::FromCE(const btVector3& c,const btVector3& e)
+{
+ btDbvtAabbMm box;
+ box.mi=c-e;box.mx=c+e;
+ return(box);
+}
+
+//
+inline btDbvtAabbMm btDbvtAabbMm::FromCR(const btVector3& c,btScalar r)
+{
+ return(FromCE(c,btVector3(r,r,r)));
+}
+
+//
+inline btDbvtAabbMm btDbvtAabbMm::FromMM(const btVector3& mi,const btVector3& mx)
+{
+ btDbvtAabbMm box;
+ box.mi=mi;box.mx=mx;
+ return(box);
+}
+
+//
+inline btDbvtAabbMm btDbvtAabbMm::FromPoints(const btVector3* pts,int n)
+{
+ btDbvtAabbMm box;
+ box.mi=box.mx=pts[0];
+ for(int i=1;i0) mx.setX(mx.x()+e[0]); else mi.setX(mi.x()+e[0]);
+ if(e.y()>0) mx.setY(mx.y()+e[1]); else mi.setY(mi.y()+e[1]);
+ if(e.z()>0) mx.setZ(mx.z()+e[2]); else mi.setZ(mi.z()+e[2]);
+}
+
+//
+DBVT_INLINE bool btDbvtAabbMm::Contain(const btDbvtAabbMm& a) const
+{
+ return( (mi.x()<=a.mi.x())&&
+ (mi.y()<=a.mi.y())&&
+ (mi.z()<=a.mi.z())&&
+ (mx.x()>=a.mx.x())&&
+ (mx.y()>=a.mx.y())&&
+ (mx.z()>=a.mx.z()));
+}
+
+//
+DBVT_INLINE int btDbvtAabbMm::Classify(const btVector3& n,btScalar o,int s) const
+{
+ btVector3 pi,px;
+ switch(s)
+ {
+ case (0+0+0): px=btVector3(mi.x(),mi.y(),mi.z());
+ pi=btVector3(mx.x(),mx.y(),mx.z());break;
+ case (1+0+0): px=btVector3(mx.x(),mi.y(),mi.z());
+ pi=btVector3(mi.x(),mx.y(),mx.z());break;
+ case (0+2+0): px=btVector3(mi.x(),mx.y(),mi.z());
+ pi=btVector3(mx.x(),mi.y(),mx.z());break;
+ case (1+2+0): px=btVector3(mx.x(),mx.y(),mi.z());
+ pi=btVector3(mi.x(),mi.y(),mx.z());break;
+ case (0+0+4): px=btVector3(mi.x(),mi.y(),mx.z());
+ pi=btVector3(mx.x(),mx.y(),mi.z());break;
+ case (1+0+4): px=btVector3(mx.x(),mi.y(),mx.z());
+ pi=btVector3(mi.x(),mx.y(),mi.z());break;
+ case (0+2+4): px=btVector3(mi.x(),mx.y(),mx.z());
+ pi=btVector3(mx.x(),mi.y(),mi.z());break;
+ case (1+2+4): px=btVector3(mx.x(),mx.y(),mx.z());
+ pi=btVector3(mi.x(),mi.y(),mi.z());break;
+ }
+ if((btDot(n,px)+o)<0) return(-1);
+ if((btDot(n,pi)+o)>=0) return(+1);
+ return(0);
+}
+
+//
+DBVT_INLINE btScalar btDbvtAabbMm::ProjectMinimum(const btVector3& v,unsigned signs) const
+{
+ const btVector3* b[]={&mx,&mi};
+ const btVector3 p( b[(signs>>0)&1]->x(),
+ b[(signs>>1)&1]->y(),
+ b[(signs>>2)&1]->z());
+ return(btDot(p,v));
+}
+
+//
+DBVT_INLINE void btDbvtAabbMm::AddSpan(const btVector3& d,btScalar& smi,btScalar& smx) const
+{
+ for(int i=0;i<3;++i)
+ {
+ if(d[i]<0)
+ { smi+=mx[i]*d[i];smx+=mi[i]*d[i]; }
+ else
+ { smi+=mi[i]*d[i];smx+=mx[i]*d[i]; }
+ }
+}
+
+//
+DBVT_INLINE bool Intersect( const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b)
+{
+#if DBVT_INT0_IMPL == DBVT_IMPL_SSE
+ const __m128 rt(_mm_or_ps( _mm_cmplt_ps(_mm_load_ps(b.mx),_mm_load_ps(a.mi)),
+ _mm_cmplt_ps(_mm_load_ps(a.mx),_mm_load_ps(b.mi))));
+#if defined (_WIN32)
+ const __int32* pu((const __int32*)&rt);
+#else
+ const int* pu((const int*)&rt);
+#endif
+ return((pu[0]|pu[1]|pu[2])==0);
+#else
+ return( (a.mi.x()<=b.mx.x())&&
+ (a.mx.x()>=b.mi.x())&&
+ (a.mi.y()<=b.mx.y())&&
+ (a.mx.y()>=b.mi.y())&&
+ (a.mi.z()<=b.mx.z())&&
+ (a.mx.z()>=b.mi.z()));
+#endif
+}
+
+
+
+//
+DBVT_INLINE bool Intersect( const btDbvtAabbMm& a,
+ const btVector3& b)
+{
+ return( (b.x()>=a.mi.x())&&
+ (b.y()>=a.mi.y())&&
+ (b.z()>=a.mi.z())&&
+ (b.x()<=a.mx.x())&&
+ (b.y()<=a.mx.y())&&
+ (b.z()<=a.mx.z()));
+}
+
+
+
+
+
+//////////////////////////////////////
+
+
+//
+DBVT_INLINE btScalar Proximity( const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b)
+{
+ const btVector3 d=(a.mi+a.mx)-(b.mi+b.mx);
+ return(btFabs(d.x())+btFabs(d.y())+btFabs(d.z()));
+}
+
+
+
+//
+DBVT_INLINE int Select( const btDbvtAabbMm& o,
+ const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b)
+{
+#if DBVT_SELECT_IMPL == DBVT_IMPL_SSE
+
+#if defined (_WIN32)
+ static ATTRIBUTE_ALIGNED16(const unsigned __int32) mask[]={0x7fffffff,0x7fffffff,0x7fffffff,0x7fffffff};
+#else
+ static ATTRIBUTE_ALIGNED16(const unsigned int) mask[]={0x7fffffff,0x7fffffff,0x7fffffff,0x00000000 /*0x7fffffff*/};
+#endif
+ ///@todo: the intrinsic version is 11% slower
+#if DBVT_USE_INTRINSIC_SSE
+
+ union btSSEUnion ///NOTE: if we use more intrinsics, move btSSEUnion into the LinearMath directory
+ {
+ __m128 ssereg;
+ float floats[4];
+ int ints[4];
+ };
+
+ __m128 omi(_mm_load_ps(o.mi));
+ omi=_mm_add_ps(omi,_mm_load_ps(o.mx));
+ __m128 ami(_mm_load_ps(a.mi));
+ ami=_mm_add_ps(ami,_mm_load_ps(a.mx));
+ ami=_mm_sub_ps(ami,omi);
+ ami=_mm_and_ps(ami,_mm_load_ps((const float*)mask));
+ __m128 bmi(_mm_load_ps(b.mi));
+ bmi=_mm_add_ps(bmi,_mm_load_ps(b.mx));
+ bmi=_mm_sub_ps(bmi,omi);
+ bmi=_mm_and_ps(bmi,_mm_load_ps((const float*)mask));
+ __m128 t0(_mm_movehl_ps(ami,ami));
+ ami=_mm_add_ps(ami,t0);
+ ami=_mm_add_ss(ami,_mm_shuffle_ps(ami,ami,1));
+ __m128 t1(_mm_movehl_ps(bmi,bmi));
+ bmi=_mm_add_ps(bmi,t1);
+ bmi=_mm_add_ss(bmi,_mm_shuffle_ps(bmi,bmi,1));
+
+ btSSEUnion tmp;
+ tmp.ssereg = _mm_cmple_ss(bmi,ami);
+ return tmp.ints[0]&1;
+
+#else
+ ATTRIBUTE_ALIGNED16(__int32 r[1]);
+ __asm
+ {
+ mov eax,o
+ mov ecx,a
+ mov edx,b
+ movaps xmm0,[eax]
+ movaps xmm5,mask
+ addps xmm0,[eax+16]
+ movaps xmm1,[ecx]
+ movaps xmm2,[edx]
+ addps xmm1,[ecx+16]
+ addps xmm2,[edx+16]
+ subps xmm1,xmm0
+ subps xmm2,xmm0
+ andps xmm1,xmm5
+ andps xmm2,xmm5
+ movhlps xmm3,xmm1
+ movhlps xmm4,xmm2
+ addps xmm1,xmm3
+ addps xmm2,xmm4
+ pshufd xmm3,xmm1,1
+ pshufd xmm4,xmm2,1
+ addss xmm1,xmm3
+ addss xmm2,xmm4
+ cmpless xmm2,xmm1
+ movss r,xmm2
+ }
+ return(r[0]&1);
+#endif
+#else
+ return(Proximity(o,a)b.mx[i]) r.mx[i]=a.mx[i]; else r.mx[i]=b.mx[i];
+ }
+#endif
+}
+
+//
+DBVT_INLINE bool NotEqual( const btDbvtAabbMm& a,
+ const btDbvtAabbMm& b)
+{
+ return( (a.mi.x()!=b.mi.x())||
+ (a.mi.y()!=b.mi.y())||
+ (a.mi.z()!=b.mi.z())||
+ (a.mx.x()!=b.mx.x())||
+ (a.mx.y()!=b.mx.y())||
+ (a.mx.z()!=b.mx.z()));
+}
+
+//
+// Inline's
+//
+
+//
+DBVT_PREFIX
+inline void btDbvt::enumNodes( const btDbvtNode* root,
+ DBVT_IPOLICY)
+{
+ DBVT_CHECKTYPE
+ policy.Process(root);
+ if(root->isinternal())
+ {
+ enumNodes(root->childs[0],policy);
+ enumNodes(root->childs[1],policy);
+ }
+}
+
+//
+DBVT_PREFIX
+inline void btDbvt::enumLeaves( const btDbvtNode* root,
+ DBVT_IPOLICY)
+{
+ DBVT_CHECKTYPE
+ if(root->isinternal())
+ {
+ enumLeaves(root->childs[0],policy);
+ enumLeaves(root->childs[1],policy);
+ }
+ else
+ {
+ policy.Process(root);
+ }
+}
+
+//
+DBVT_PREFIX
+inline void btDbvt::collideTT( const btDbvtNode* root0,
+ const btDbvtNode* root1,
+ DBVT_IPOLICY)
+{
+ DBVT_CHECKTYPE
+ if(root0&&root1)
+ {
+ int depth=1;
+ int treshold=DOUBLE_STACKSIZE-4;
+ btAlignedObjectArray stkStack;
+ stkStack.resize(DOUBLE_STACKSIZE);
+ stkStack[0]=sStkNN(root0,root1);
+ do {
+ sStkNN p=stkStack[--depth];
+ if(depth>treshold)
+ {
+ stkStack.resize(stkStack.size()*2);
+ treshold=stkStack.size()-4;
+ }
+ if(p.a==p.b)
+ {
+ if(p.a->isinternal())
+ {
+ stkStack[depth++]=sStkNN(p.a->childs[0],p.a->childs[0]);
+ stkStack[depth++]=sStkNN(p.a->childs[1],p.a->childs[1]);
+ stkStack[depth++]=sStkNN(p.a->childs[0],p.a->childs[1]);
+ }
+ }
+ else if(Intersect(p.a->volume,p.b->volume))
+ {
+ if(p.a->isinternal())
+ {
+ if(p.b->isinternal())
+ {
+ stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[0]);
+ stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[0]);
+ stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[1]);
+ stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[1]);
+ }
+ else
+ {
+ stkStack[depth++]=sStkNN(p.a->childs[0],p.b);
+ stkStack[depth++]=sStkNN(p.a->childs[1],p.b);
+ }
+ }
+ else
+ {
+ if(p.b->isinternal())
+ {
+ stkStack[depth++]=sStkNN(p.a,p.b->childs[0]);
+ stkStack[depth++]=sStkNN(p.a,p.b->childs[1]);
+ }
+ else
+ {
+ policy.Process(p.a,p.b);
+ }
+ }
+ }
+ } while(depth);
+ }
+}
+
+
+
+DBVT_PREFIX
+inline void btDbvt::collideTTpersistentStack( const btDbvtNode* root0,
+ const btDbvtNode* root1,
+ DBVT_IPOLICY)
+{
+ DBVT_CHECKTYPE
+ if(root0&&root1)
+ {
+ int depth=1;
+ int treshold=DOUBLE_STACKSIZE-4;
+
+ m_stkStack.resize(DOUBLE_STACKSIZE);
+ m_stkStack[0]=sStkNN(root0,root1);
+ do {
+ sStkNN p=m_stkStack[--depth];
+ if(depth>treshold)
+ {
+ m_stkStack.resize(m_stkStack.size()*2);
+ treshold=m_stkStack.size()-4;
+ }
+ if(p.a==p.b)
+ {
+ if(p.a->isinternal())
+ {
+ m_stkStack[depth++]=sStkNN(p.a->childs[0],p.a->childs[0]);
+ m_stkStack[depth++]=sStkNN(p.a->childs[1],p.a->childs[1]);
+ m_stkStack[depth++]=sStkNN(p.a->childs[0],p.a->childs[1]);
+ }
+ }
+ else if(Intersect(p.a->volume,p.b->volume))
+ {
+ if(p.a->isinternal())
+ {
+ if(p.b->isinternal())
+ {
+ m_stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[0]);
+ m_stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[0]);
+ m_stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[1]);
+ m_stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[1]);
+ }
+ else
+ {
+ m_stkStack[depth++]=sStkNN(p.a->childs[0],p.b);
+ m_stkStack[depth++]=sStkNN(p.a->childs[1],p.b);
+ }
+ }
+ else
+ {
+ if(p.b->isinternal())
+ {
+ m_stkStack[depth++]=sStkNN(p.a,p.b->childs[0]);
+ m_stkStack[depth++]=sStkNN(p.a,p.b->childs[1]);
+ }
+ else
+ {
+ policy.Process(p.a,p.b);
+ }
+ }
+ }
+ } while(depth);
+ }
+}
+
+#if 0
+//
+DBVT_PREFIX
+inline void btDbvt::collideTT( const btDbvtNode* root0,
+ const btDbvtNode* root1,
+ const btTransform& xform,
+ DBVT_IPOLICY)
+{
+ DBVT_CHECKTYPE
+ if(root0&&root1)
+ {
+ int depth=1;
+ int treshold=DOUBLE_STACKSIZE-4;
+ btAlignedObjectArray stkStack;
+ stkStack.resize(DOUBLE_STACKSIZE);
+ stkStack[0]=sStkNN(root0,root1);
+ do {
+ sStkNN p=stkStack[--depth];
+ if(Intersect(p.a->volume,p.b->volume,xform))
+ {
+ if(depth>treshold)
+ {
+ stkStack.resize(stkStack.size()*2);
+ treshold=stkStack.size()-4;
+ }
+ if(p.a->isinternal())
+ {
+ if(p.b->isinternal())
+ {
+ stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[0]);
+ stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[0]);
+ stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[1]);
+ stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[1]);
+ }
+ else
+ {
+ stkStack[depth++]=sStkNN(p.a->childs[0],p.b);
+ stkStack[depth++]=sStkNN(p.a->childs[1],p.b);
+ }
+ }
+ else
+ {
+ if(p.b->isinternal())
+ {
+ stkStack[depth++]=sStkNN(p.a,p.b->childs[0]);
+ stkStack[depth++]=sStkNN(p.a,p.b->childs[1]);
+ }
+ else
+ {
+ policy.Process(p.a,p.b);
+ }
+ }
+ }
+ } while(depth);
+ }
+}
+//
+DBVT_PREFIX
+inline void btDbvt::collideTT( const btDbvtNode* root0,
+ const btTransform& xform0,
+ const btDbvtNode* root1,
+ const btTransform& xform1,
+ DBVT_IPOLICY)
+{
+ const btTransform xform=xform0.inverse()*xform1;
+ collideTT(root0,root1,xform,policy);
+}
+#endif
+
+//
+DBVT_PREFIX
+inline void btDbvt::collideTV( const btDbvtNode* root,
+ const btDbvtVolume& vol,
+ DBVT_IPOLICY) const
+{
+ DBVT_CHECKTYPE
+ if(root)
+ {
+ ATTRIBUTE_ALIGNED16(btDbvtVolume) volume(vol);
+ btAlignedObjectArray stack;
+ stack.resize(0);
+ stack.reserve(SIMPLE_STACKSIZE);
+ stack.push_back(root);
+ do {
+ const btDbvtNode* n=stack[stack.size()-1];
+ stack.pop_back();
+ if(Intersect(n->volume,volume))
+ {
+ if(n->isinternal())
+ {
+ stack.push_back(n->childs[0]);
+ stack.push_back(n->childs[1]);
+ }
+ else
+ {
+ policy.Process(n);
+ }
+ }
+ } while(stack.size()>0);
+ }
+}
+
+DBVT_PREFIX
+inline void btDbvt::rayTestInternal( const btDbvtNode* root,
+ const btVector3& rayFrom,
+ const btVector3& rayTo,
+ const btVector3& rayDirectionInverse,
+ unsigned int signs[3],
+ btScalar lambda_max,
+ const btVector3& aabbMin,
+ const btVector3& aabbMax,
+ DBVT_IPOLICY) const
+{
+ (void) rayTo;
+ DBVT_CHECKTYPE
+ if(root)
+ {
+ btVector3 resultNormal;
+
+ int depth=1;
+ int treshold=DOUBLE_STACKSIZE-2;
+ btAlignedObjectArray& stack = m_rayTestStack;
+ stack.resize(DOUBLE_STACKSIZE);
+ stack[0]=root;
+ btVector3 bounds[2];
+ do
+ {
+ const btDbvtNode* node=stack[--depth];
+ bounds[0] = node->volume.Mins()-aabbMax;
+ bounds[1] = node->volume.Maxs()-aabbMin;
+ btScalar tmin=1.f,lambda_min=0.f;
+ unsigned int result1=false;
+ result1 = btRayAabb2(rayFrom,rayDirectionInverse,signs,bounds,tmin,lambda_min,lambda_max);
+ if(result1)
+ {
+ if(node->isinternal())
+ {
+ if(depth>treshold)
+ {
+ stack.resize(stack.size()*2);
+ treshold=stack.size()-2;
+ }
+ stack[depth++]=node->childs[0];
+ stack[depth++]=node->childs[1];
+ }
+ else
+ {
+ policy.Process(node);
+ }
+ }
+ } while(depth);
+ }
+}
+
+//
+DBVT_PREFIX
+inline void btDbvt::rayTest( const btDbvtNode* root,
+ const btVector3& rayFrom,
+ const btVector3& rayTo,
+ DBVT_IPOLICY)
+{
+ DBVT_CHECKTYPE
+ if(root)
+ {
+ btVector3 rayDir = (rayTo-rayFrom);
+ rayDir.normalize ();
+
+ ///what about division by zero? --> just set rayDirection[i] to INF/BT_LARGE_FLOAT
+ btVector3 rayDirectionInverse;
+ rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0];
+ rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[1];
+ rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[2];
+ unsigned int signs[3] = { rayDirectionInverse[0] < 0.0, rayDirectionInverse[1] < 0.0, rayDirectionInverse[2] < 0.0};
+
+ btScalar lambda_max = rayDir.dot(rayTo-rayFrom);
+
+ btVector3 resultNormal;
+
+ btAlignedObjectArray stack;
+
+ int depth=1;
+ int treshold=DOUBLE_STACKSIZE-2;
+
+ stack.resize(DOUBLE_STACKSIZE);
+ stack[0]=root;
+ btVector3 bounds[2];
+ do {
+ const btDbvtNode* node=stack[--depth];
+
+ bounds[0] = node->volume.Mins();
+ bounds[1] = node->volume.Maxs();
+
+ btScalar tmin=1.f,lambda_min=0.f;
+ unsigned int result1 = btRayAabb2(rayFrom,rayDirectionInverse,signs,bounds,tmin,lambda_min,lambda_max);
+
+#ifdef COMPARE_BTRAY_AABB2
+ btScalar param=1.f;
+ bool result2 = btRayAabb(rayFrom,rayTo,node->volume.Mins(),node->volume.Maxs(),param,resultNormal);
+ btAssert(result1 == result2);
+#endif //TEST_BTRAY_AABB2
+
+ if(result1)
+ {
+ if(node->isinternal())
+ {
+ if(depth>treshold)
+ {
+ stack.resize(stack.size()*2);
+ treshold=stack.size()-2;
+ }
+ stack[depth++]=node->childs[0];
+ stack[depth++]=node->childs[1];
+ }
+ else
+ {
+ policy.Process(node);
+ }
+ }
+ } while(depth);
+
+ }
+}
+
+//
+DBVT_PREFIX
+inline void btDbvt::collideKDOP(const btDbvtNode* root,
+ const btVector3* normals,
+ const btScalar* offsets,
+ int count,
+ DBVT_IPOLICY)
+{
+ DBVT_CHECKTYPE
+ if(root)
+ {
+ const int inside=(1< stack;
+ int signs[sizeof(unsigned)*8];
+ btAssert(count=0)?1:0)+
+ ((normals[i].y()>=0)?2:0)+
+ ((normals[i].z()>=0)?4:0);
+ }
+ stack.reserve(SIMPLE_STACKSIZE);
+ stack.push_back(sStkNP(root,0));
+ do {
+ sStkNP se=stack[stack.size()-1];
+ bool out=false;
+ stack.pop_back();
+ for(int i=0,j=1;(!out)&&(ivolume.Classify(normals[i],offsets[i],signs[i]);
+ switch(side)
+ {
+ case -1: out=true;break;
+ case +1: se.mask|=j;break;
+ }
+ }
+ }
+ if(!out)
+ {
+ if((se.mask!=inside)&&(se.node->isinternal()))
+ {
+ stack.push_back(sStkNP(se.node->childs[0],se.mask));
+ stack.push_back(sStkNP(se.node->childs[1],se.mask));
+ }
+ else
+ {
+ if(policy.AllLeaves(se.node)) enumLeaves(se.node,policy);
+ }
+ }
+ } while(stack.size());
+ }
+}
+
+//
+DBVT_PREFIX
+inline void btDbvt::collideOCL( const btDbvtNode* root,
+ const btVector3* normals,
+ const btScalar* offsets,
+ const btVector3& sortaxis,
+ int count,
+ DBVT_IPOLICY,
+ bool fsort)
+{
+ DBVT_CHECKTYPE
+ if(root)
+ {
+ const unsigned srtsgns=(sortaxis[0]>=0?1:0)+
+ (sortaxis[1]>=0?2:0)+
+ (sortaxis[2]>=0?4:0);
+ const int inside=(1< stock;
+ btAlignedObjectArray ifree;
+ btAlignedObjectArray stack;
+ int signs[sizeof(unsigned)*8];
+ btAssert(count=0)?1:0)+
+ ((normals[i].y()>=0)?2:0)+
+ ((normals[i].z()>=0)?4:0);
+ }
+ stock.reserve(SIMPLE_STACKSIZE);
+ stack.reserve(SIMPLE_STACKSIZE);
+ ifree.reserve(SIMPLE_STACKSIZE);
+ stack.push_back(allocate(ifree,stock,sStkNPS(root,0,root->volume.ProjectMinimum(sortaxis,srtsgns))));
+ do {
+ const int id=stack[stack.size()-1];
+ sStkNPS se=stock[id];
+ stack.pop_back();ifree.push_back(id);
+ if(se.mask!=inside)
+ {
+ bool out=false;
+ for(int i=0,j=1;(!out)&&(ivolume.Classify(normals[i],offsets[i],signs[i]);
+ switch(side)
+ {
+ case -1: out=true;break;
+ case +1: se.mask|=j;break;
+ }
+ }
+ }
+ if(out) continue;
+ }
+ if(policy.Descent(se.node))
+ {
+ if(se.node->isinternal())
+ {
+ const btDbvtNode* pns[]={ se.node->childs[0],se.node->childs[1]};
+ sStkNPS nes[]={ sStkNPS(pns[0],se.mask,pns[0]->volume.ProjectMinimum(sortaxis,srtsgns)),
+ sStkNPS(pns[1],se.mask,pns[1]->volume.ProjectMinimum(sortaxis,srtsgns))};
+ const int q=nes[0].value0))
+ {
+ /* Insert 0 */
+ j=nearest(&stack[0],&stock[0],nes[q].value,0,stack.size());
+ stack.push_back(0);
+#if DBVT_USE_MEMMOVE
+ memmove(&stack[j+1],&stack[j],sizeof(int)*(stack.size()-j-1));
+#else
+ for(int k=stack.size()-1;k>j;--k) stack[k]=stack[k-1];
+#endif
+ stack[j]=allocate(ifree,stock,nes[q]);
+ /* Insert 1 */
+ j=nearest(&stack[0],&stock[0],nes[1-q].value,j,stack.size());
+ stack.push_back(0);
+#if DBVT_USE_MEMMOVE
+ memmove(&stack[j+1],&stack[j],sizeof(int)*(stack.size()-j-1));
+#else
+ for(int k=stack.size()-1;k>j;--k) stack[k]=stack[k-1];
+#endif
+ stack[j]=allocate(ifree,stock,nes[1-q]);
+ }
+ else
+ {
+ stack.push_back(allocate(ifree,stock,nes[q]));
+ stack.push_back(allocate(ifree,stock,nes[1-q]));
+ }
+ }
+ else
+ {
+ policy.Process(se.node,se.value);
+ }
+ }
+ } while(stack.size());
+ }
+}
+
+//
+DBVT_PREFIX
+inline void btDbvt::collideTU( const btDbvtNode* root,
+ DBVT_IPOLICY)
+{
+ DBVT_CHECKTYPE
+ if(root)
+ {
+ btAlignedObjectArray stack;
+ stack.reserve(SIMPLE_STACKSIZE);
+ stack.push_back(root);
+ do {
+ const btDbvtNode* n=stack[stack.size()-1];
+ stack.pop_back();
+ if(policy.Descent(n))
+ {
+ if(n->isinternal())
+ { stack.push_back(n->childs[0]);stack.push_back(n->childs[1]); }
+ else
+ { policy.Process(n); }
+ }
+ } while(stack.size()>0);
+ }
+}
+
+//
+// PP Cleanup
+//
+
+#undef DBVT_USE_MEMMOVE
+#undef DBVT_USE_TEMPLATE
+#undef DBVT_VIRTUAL_DTOR
+#undef DBVT_VIRTUAL
+#undef DBVT_PREFIX
+#undef DBVT_IPOLICY
+#undef DBVT_CHECKTYPE
+#undef DBVT_IMPL_GENERIC
+#undef DBVT_IMPL_SSE
+#undef DBVT_USE_INTRINSIC_SSE
+#undef DBVT_SELECT_IMPL
+#undef DBVT_MERGE_IMPL
+#undef DBVT_INT0_IMPL
+
+#endif
diff --git a/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp
new file mode 100644
index 00000000..75cfac64
--- /dev/null
+++ b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp
@@ -0,0 +1,796 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+///btDbvtBroadphase implementation by Nathanael Presson
+
+#include "btDbvtBroadphase.h"
+
+//
+// Profiling
+//
+
+#if DBVT_BP_PROFILE||DBVT_BP_ENABLE_BENCHMARK
+#include
+#endif
+
+#if DBVT_BP_PROFILE
+struct ProfileScope
+{
+ __forceinline ProfileScope(btClock& clock,unsigned long& value) :
+ m_clock(&clock),m_value(&value),m_base(clock.getTimeMicroseconds())
+ {
+ }
+ __forceinline ~ProfileScope()
+ {
+ (*m_value)+=m_clock->getTimeMicroseconds()-m_base;
+ }
+ btClock* m_clock;
+ unsigned long* m_value;
+ unsigned long m_base;
+};
+#define SPC(_value_) ProfileScope spc_scope(m_clock,_value_)
+#else
+#define SPC(_value_)
+#endif
+
+//
+// Helpers
+//
+
+//
+template
+static inline void listappend(T* item,T*& list)
+{
+ item->links[0]=0;
+ item->links[1]=list;
+ if(list) list->links[0]=item;
+ list=item;
+}
+
+//
+template
+static inline void listremove(T* item,T*& list)
+{
+ if(item->links[0]) item->links[0]->links[1]=item->links[1]; else list=item->links[1];
+ if(item->links[1]) item->links[1]->links[0]=item->links[0];
+}
+
+//
+template
+static inline int listcount(T* root)
+{
+ int n=0;
+ while(root) { ++n;root=root->links[1]; }
+ return(n);
+}
+
+//
+template
+static inline void clear(T& value)
+{
+ static const struct ZeroDummy : T {} zerodummy;
+ value=zerodummy;
+}
+
+//
+// Colliders
+//
+
+/* Tree collider */
+struct btDbvtTreeCollider : btDbvt::ICollide
+{
+ btDbvtBroadphase* pbp;
+ btDbvtProxy* proxy;
+ btDbvtTreeCollider(btDbvtBroadphase* p) : pbp(p) {}
+ void Process(const btDbvtNode* na,const btDbvtNode* nb)
+ {
+ if(na!=nb)
+ {
+ btDbvtProxy* pa=(btDbvtProxy*)na->data;
+ btDbvtProxy* pb=(btDbvtProxy*)nb->data;
+#if DBVT_BP_SORTPAIRS
+ if(pa->m_uniqueId>pb->m_uniqueId)
+ btSwap(pa,pb);
+#endif
+ pbp->m_paircache->addOverlappingPair(pa,pb);
+ ++pbp->m_newpairs;
+ }
+ }
+ void Process(const btDbvtNode* n)
+ {
+ Process(n,proxy->leaf);
+ }
+};
+
+//
+// btDbvtBroadphase
+//
+
+//
+btDbvtBroadphase::btDbvtBroadphase(btOverlappingPairCache* paircache)
+{
+ m_deferedcollide = false;
+ m_needcleanup = true;
+ m_releasepaircache = (paircache!=0)?false:true;
+ m_prediction = 0;
+ m_stageCurrent = 0;
+ m_fixedleft = 0;
+ m_fupdates = 1;
+ m_dupdates = 0;
+ m_cupdates = 10;
+ m_newpairs = 1;
+ m_updates_call = 0;
+ m_updates_done = 0;
+ m_updates_ratio = 0;
+ m_paircache = paircache? paircache : new(btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16)) btHashedOverlappingPairCache();
+ m_gid = 0;
+ m_pid = 0;
+ m_cid = 0;
+ for(int i=0;i<=STAGECOUNT;++i)
+ {
+ m_stageRoots[i]=0;
+ }
+#if DBVT_BP_PROFILE
+ clear(m_profiling);
+#endif
+}
+
+//
+btDbvtBroadphase::~btDbvtBroadphase()
+{
+ if(m_releasepaircache)
+ {
+ m_paircache->~btOverlappingPairCache();
+ btAlignedFree(m_paircache);
+ }
+}
+
+//
+btBroadphaseProxy* btDbvtBroadphase::createProxy( const btVector3& aabbMin,
+ const btVector3& aabbMax,
+ int /*shapeType*/,
+ void* userPtr,
+ short int collisionFilterGroup,
+ short int collisionFilterMask,
+ btDispatcher* /*dispatcher*/,
+ void* /*multiSapProxy*/)
+{
+ btDbvtProxy* proxy=new(btAlignedAlloc(sizeof(btDbvtProxy),16)) btDbvtProxy( aabbMin,aabbMax,userPtr,
+ collisionFilterGroup,
+ collisionFilterMask);
+
+ btDbvtAabbMm aabb = btDbvtVolume::FromMM(aabbMin,aabbMax);
+
+ //bproxy->aabb = btDbvtVolume::FromMM(aabbMin,aabbMax);
+ proxy->stage = m_stageCurrent;
+ proxy->m_uniqueId = ++m_gid;
+ proxy->leaf = m_sets[0].insert(aabb,proxy);
+ listappend(proxy,m_stageRoots[m_stageCurrent]);
+ if(!m_deferedcollide)
+ {
+ btDbvtTreeCollider collider(this);
+ collider.proxy=proxy;
+ m_sets[0].collideTV(m_sets[0].m_root,aabb,collider);
+ m_sets[1].collideTV(m_sets[1].m_root,aabb,collider);
+ }
+ return(proxy);
+}
+
+//
+void btDbvtBroadphase::destroyProxy( btBroadphaseProxy* absproxy,
+ btDispatcher* dispatcher)
+{
+ btDbvtProxy* proxy=(btDbvtProxy*)absproxy;
+ if(proxy->stage==STAGECOUNT)
+ m_sets[1].remove(proxy->leaf);
+ else
+ m_sets[0].remove(proxy->leaf);
+ listremove(proxy,m_stageRoots[proxy->stage]);
+ m_paircache->removeOverlappingPairsContainingProxy(proxy,dispatcher);
+ btAlignedFree(proxy);
+ m_needcleanup=true;
+}
+
+void btDbvtBroadphase::getAabb(btBroadphaseProxy* absproxy,btVector3& aabbMin, btVector3& aabbMax ) const
+{
+ btDbvtProxy* proxy=(btDbvtProxy*)absproxy;
+ aabbMin = proxy->m_aabbMin;
+ aabbMax = proxy->m_aabbMax;
+}
+
+struct BroadphaseRayTester : btDbvt::ICollide
+{
+ btBroadphaseRayCallback& m_rayCallback;
+ BroadphaseRayTester(btBroadphaseRayCallback& orgCallback)
+ :m_rayCallback(orgCallback)
+ {
+ }
+ void Process(const btDbvtNode* leaf)
+ {
+ btDbvtProxy* proxy=(btDbvtProxy*)leaf->data;
+ m_rayCallback.process(proxy);
+ }
+};
+
+void btDbvtBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback,const btVector3& aabbMin,const btVector3& aabbMax)
+{
+ BroadphaseRayTester callback(rayCallback);
+
+ m_sets[0].rayTestInternal( m_sets[0].m_root,
+ rayFrom,
+ rayTo,
+ rayCallback.m_rayDirectionInverse,
+ rayCallback.m_signs,
+ rayCallback.m_lambda_max,
+ aabbMin,
+ aabbMax,
+ callback);
+
+ m_sets[1].rayTestInternal( m_sets[1].m_root,
+ rayFrom,
+ rayTo,
+ rayCallback.m_rayDirectionInverse,
+ rayCallback.m_signs,
+ rayCallback.m_lambda_max,
+ aabbMin,
+ aabbMax,
+ callback);
+
+}
+
+
+struct BroadphaseAabbTester : btDbvt::ICollide
+{
+ btBroadphaseAabbCallback& m_aabbCallback;
+ BroadphaseAabbTester(btBroadphaseAabbCallback& orgCallback)
+ :m_aabbCallback(orgCallback)
+ {
+ }
+ void Process(const btDbvtNode* leaf)
+ {
+ btDbvtProxy* proxy=(btDbvtProxy*)leaf->data;
+ m_aabbCallback.process(proxy);
+ }
+};
+
+void btDbvtBroadphase::aabbTest(const btVector3& aabbMin,const btVector3& aabbMax,btBroadphaseAabbCallback& aabbCallback)
+{
+ BroadphaseAabbTester callback(aabbCallback);
+
+ const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(aabbMin,aabbMax);
+ //process all children, that overlap with the given AABB bounds
+ m_sets[0].collideTV(m_sets[0].m_root,bounds,callback);
+ m_sets[1].collideTV(m_sets[1].m_root,bounds,callback);
+
+}
+
+
+
+//
+void btDbvtBroadphase::setAabb( btBroadphaseProxy* absproxy,
+ const btVector3& aabbMin,
+ const btVector3& aabbMax,
+ btDispatcher* /*dispatcher*/)
+{
+ btDbvtProxy* proxy=(btDbvtProxy*)absproxy;
+ ATTRIBUTE_ALIGNED16(btDbvtVolume) aabb=btDbvtVolume::FromMM(aabbMin,aabbMax);
+#if DBVT_BP_PREVENTFALSEUPDATE
+ if(NotEqual(aabb,proxy->leaf->volume))
+#endif
+ {
+ bool docollide=false;
+ if(proxy->stage==STAGECOUNT)
+ {/* fixed -> dynamic set */
+ m_sets[1].remove(proxy->leaf);
+ proxy->leaf=m_sets[0].insert(aabb,proxy);
+ docollide=true;
+ }
+ else
+ {/* dynamic set */
+ ++m_updates_call;
+ if(Intersect(proxy->leaf->volume,aabb))
+ {/* Moving */
+
+ const btVector3 delta=aabbMin-proxy->m_aabbMin;
+ btVector3 velocity(((proxy->m_aabbMax-proxy->m_aabbMin)/2)*m_prediction);
+ if(delta[0]<0) velocity[0]=-velocity[0];
+ if(delta[1]<0) velocity[1]=-velocity[1];
+ if(delta[2]<0) velocity[2]=-velocity[2];
+ if (
+#ifdef DBVT_BP_MARGIN
+ m_sets[0].update(proxy->leaf,aabb,velocity,DBVT_BP_MARGIN)
+#else
+ m_sets[0].update(proxy->leaf,aabb,velocity)
+#endif
+ )
+ {
+ ++m_updates_done;
+ docollide=true;
+ }
+ }
+ else
+ {/* Teleporting */
+ m_sets[0].update(proxy->leaf,aabb);
+ ++m_updates_done;
+ docollide=true;
+ }
+ }
+ listremove(proxy,m_stageRoots[proxy->stage]);
+ proxy->m_aabbMin = aabbMin;
+ proxy->m_aabbMax = aabbMax;
+ proxy->stage = m_stageCurrent;
+ listappend(proxy,m_stageRoots[m_stageCurrent]);
+ if(docollide)
+ {
+ m_needcleanup=true;
+ if(!m_deferedcollide)
+ {
+ btDbvtTreeCollider collider(this);
+ m_sets[1].collideTTpersistentStack(m_sets[1].m_root,proxy->leaf,collider);
+ m_sets[0].collideTTpersistentStack(m_sets[0].m_root,proxy->leaf,collider);
+ }
+ }
+ }
+}
+
+
+//
+void btDbvtBroadphase::setAabbForceUpdate( btBroadphaseProxy* absproxy,
+ const btVector3& aabbMin,
+ const btVector3& aabbMax,
+ btDispatcher* /*dispatcher*/)
+{
+ btDbvtProxy* proxy=(btDbvtProxy*)absproxy;
+ ATTRIBUTE_ALIGNED16(btDbvtVolume) aabb=btDbvtVolume::FromMM(aabbMin,aabbMax);
+ bool docollide=false;
+ if(proxy->stage==STAGECOUNT)
+ {/* fixed -> dynamic set */
+ m_sets[1].remove(proxy->leaf);
+ proxy->leaf=m_sets[0].insert(aabb,proxy);
+ docollide=true;
+ }
+ else
+ {/* dynamic set */
+ ++m_updates_call;
+ /* Teleporting */
+ m_sets[0].update(proxy->leaf,aabb);
+ ++m_updates_done;
+ docollide=true;
+ }
+ listremove(proxy,m_stageRoots[proxy->stage]);
+ proxy->m_aabbMin = aabbMin;
+ proxy->m_aabbMax = aabbMax;
+ proxy->stage = m_stageCurrent;
+ listappend(proxy,m_stageRoots[m_stageCurrent]);
+ if(docollide)
+ {
+ m_needcleanup=true;
+ if(!m_deferedcollide)
+ {
+ btDbvtTreeCollider collider(this);
+ m_sets[1].collideTTpersistentStack(m_sets[1].m_root,proxy->leaf,collider);
+ m_sets[0].collideTTpersistentStack(m_sets[0].m_root,proxy->leaf,collider);
+ }
+ }
+}
+
+//
+void btDbvtBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
+{
+ collide(dispatcher);
+#if DBVT_BP_PROFILE
+ if(0==(m_pid%DBVT_BP_PROFILING_RATE))
+ {
+ printf("fixed(%u) dynamics(%u) pairs(%u)\r\n",m_sets[1].m_leaves,m_sets[0].m_leaves,m_paircache->getNumOverlappingPairs());
+ unsigned int total=m_profiling.m_total;
+ if(total<=0) total=1;
+ printf("ddcollide: %u%% (%uus)\r\n",(50+m_profiling.m_ddcollide*100)/total,m_profiling.m_ddcollide/DBVT_BP_PROFILING_RATE);
+ printf("fdcollide: %u%% (%uus)\r\n",(50+m_profiling.m_fdcollide*100)/total,m_profiling.m_fdcollide/DBVT_BP_PROFILING_RATE);
+ printf("cleanup: %u%% (%uus)\r\n",(50+m_profiling.m_cleanup*100)/total,m_profiling.m_cleanup/DBVT_BP_PROFILING_RATE);
+ printf("total: %uus\r\n",total/DBVT_BP_PROFILING_RATE);
+ const unsigned long sum=m_profiling.m_ddcollide+
+ m_profiling.m_fdcollide+
+ m_profiling.m_cleanup;
+ printf("leaked: %u%% (%uus)\r\n",100-((50+sum*100)/total),(total-sum)/DBVT_BP_PROFILING_RATE);
+ printf("job counts: %u%%\r\n",(m_profiling.m_jobcount*100)/((m_sets[0].m_leaves+m_sets[1].m_leaves)*DBVT_BP_PROFILING_RATE));
+ clear(m_profiling);
+ m_clock.reset();
+ }
+#endif
+
+ performDeferredRemoval(dispatcher);
+
+}
+
+void btDbvtBroadphase::performDeferredRemoval(btDispatcher* dispatcher)
+{
+
+ if (m_paircache->hasDeferredRemoval())
+ {
+
+ btBroadphasePairArray& overlappingPairArray = m_paircache->getOverlappingPairArray();
+
+ //perform a sort, to find duplicates and to sort 'invalid' pairs to the end
+ overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
+
+ int invalidPair = 0;
+
+
+ int i;
+
+ btBroadphasePair previousPair;
+ previousPair.m_pProxy0 = 0;
+ previousPair.m_pProxy1 = 0;
+ previousPair.m_algorithm = 0;
+
+
+ for (i=0;ileaf->volume,pb->leaf->volume);
+
+ if (hasOverlap)
+ {
+ needsRemoval = false;
+ } else
+ {
+ needsRemoval = true;
+ }
+ } else
+ {
+ //remove duplicate
+ needsRemoval = true;
+ //should have no algorithm
+ btAssert(!pair.m_algorithm);
+ }
+
+ if (needsRemoval)
+ {
+ m_paircache->cleanOverlappingPair(pair,dispatcher);
+
+ pair.m_pProxy0 = 0;
+ pair.m_pProxy1 = 0;
+ invalidPair++;
+ }
+
+ }
+
+ //perform a sort, to sort 'invalid' pairs to the end
+ overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
+ overlappingPairArray.resize(overlappingPairArray.size() - invalidPair);
+ }
+}
+
+//
+void btDbvtBroadphase::collide(btDispatcher* dispatcher)
+{
+ /*printf("---------------------------------------------------------\n");
+ printf("m_sets[0].m_leaves=%d\n",m_sets[0].m_leaves);
+ printf("m_sets[1].m_leaves=%d\n",m_sets[1].m_leaves);
+ printf("numPairs = %d\n",getOverlappingPairCache()->getNumOverlappingPairs());
+ {
+ int i;
+ for (i=0;igetNumOverlappingPairs();i++)
+ {
+ printf("pair[%d]=(%d,%d),",i,getOverlappingPairCache()->getOverlappingPairArray()[i].m_pProxy0->getUid(),
+ getOverlappingPairCache()->getOverlappingPairArray()[i].m_pProxy1->getUid());
+ }
+ printf("\n");
+ }
+*/
+
+
+
+ SPC(m_profiling.m_total);
+ /* optimize */
+ m_sets[0].optimizeIncremental(1+(m_sets[0].m_leaves*m_dupdates)/100);
+ if(m_fixedleft)
+ {
+ const int count=1+(m_sets[1].m_leaves*m_fupdates)/100;
+ m_sets[1].optimizeIncremental(1+(m_sets[1].m_leaves*m_fupdates)/100);
+ m_fixedleft=btMax(0,m_fixedleft-count);
+ }
+ /* dynamic -> fixed set */
+ m_stageCurrent=(m_stageCurrent+1)%STAGECOUNT;
+ btDbvtProxy* current=m_stageRoots[m_stageCurrent];
+ if(current)
+ {
+ btDbvtTreeCollider collider(this);
+ do {
+ btDbvtProxy* next=current->links[1];
+ listremove(current,m_stageRoots[current->stage]);
+ listappend(current,m_stageRoots[STAGECOUNT]);
+#if DBVT_BP_ACCURATESLEEPING
+ m_paircache->removeOverlappingPairsContainingProxy(current,dispatcher);
+ collider.proxy=current;
+ btDbvt::collideTV(m_sets[0].m_root,current->aabb,collider);
+ btDbvt::collideTV(m_sets[1].m_root,current->aabb,collider);
+#endif
+ m_sets[0].remove(current->leaf);
+ ATTRIBUTE_ALIGNED16(btDbvtVolume) curAabb=btDbvtVolume::FromMM(current->m_aabbMin,current->m_aabbMax);
+ current->leaf = m_sets[1].insert(curAabb,current);
+ current->stage = STAGECOUNT;
+ current = next;
+ } while(current);
+ m_fixedleft=m_sets[1].m_leaves;
+ m_needcleanup=true;
+ }
+ /* collide dynamics */
+ {
+ btDbvtTreeCollider collider(this);
+ if(m_deferedcollide)
+ {
+ SPC(m_profiling.m_fdcollide);
+ m_sets[0].collideTTpersistentStack(m_sets[0].m_root,m_sets[1].m_root,collider);
+ }
+ if(m_deferedcollide)
+ {
+ SPC(m_profiling.m_ddcollide);
+ m_sets[0].collideTTpersistentStack(m_sets[0].m_root,m_sets[0].m_root,collider);
+ }
+ }
+ /* clean up */
+ if(m_needcleanup)
+ {
+ SPC(m_profiling.m_cleanup);
+ btBroadphasePairArray& pairs=m_paircache->getOverlappingPairArray();
+ if(pairs.size()>0)
+ {
+
+ int ni=btMin(pairs.size(),btMax(m_newpairs,(pairs.size()*m_cupdates)/100));
+ for(int i=0;ileaf->volume,pb->leaf->volume))
+ {
+#if DBVT_BP_SORTPAIRS
+ if(pa->m_uniqueId>pb->m_uniqueId)
+ btSwap(pa,pb);
+#endif
+ m_paircache->removeOverlappingPair(pa,pb,dispatcher);
+ --ni;--i;
+ }
+ }
+ if(pairs.size()>0) m_cid=(m_cid+ni)%pairs.size(); else m_cid=0;
+ }
+ }
+ ++m_pid;
+ m_newpairs=1;
+ m_needcleanup=false;
+ if(m_updates_call>0)
+ { m_updates_ratio=m_updates_done/(btScalar)m_updates_call; }
+ else
+ { m_updates_ratio=0; }
+ m_updates_done/=2;
+ m_updates_call/=2;
+}
+
+//
+void btDbvtBroadphase::optimize()
+{
+ m_sets[0].optimizeTopDown();
+ m_sets[1].optimizeTopDown();
+}
+
+//
+btOverlappingPairCache* btDbvtBroadphase::getOverlappingPairCache()
+{
+ return(m_paircache);
+}
+
+//
+const btOverlappingPairCache* btDbvtBroadphase::getOverlappingPairCache() const
+{
+ return(m_paircache);
+}
+
+//
+void btDbvtBroadphase::getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const
+{
+
+ ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds;
+
+ if(!m_sets[0].empty())
+ if(!m_sets[1].empty()) Merge( m_sets[0].m_root->volume,
+ m_sets[1].m_root->volume,bounds);
+ else
+ bounds=m_sets[0].m_root->volume;
+ else if(!m_sets[1].empty()) bounds=m_sets[1].m_root->volume;
+ else
+ bounds=btDbvtVolume::FromCR(btVector3(0,0,0),0);
+ aabbMin=bounds.Mins();
+ aabbMax=bounds.Maxs();
+}
+
+void btDbvtBroadphase::resetPool(btDispatcher* dispatcher)
+{
+
+ int totalObjects = m_sets[0].m_leaves + m_sets[1].m_leaves;
+ if (!totalObjects)
+ {
+ //reset internal dynamic tree data structures
+ m_sets[0].clear();
+ m_sets[1].clear();
+
+ m_deferedcollide = false;
+ m_needcleanup = true;
+ m_stageCurrent = 0;
+ m_fixedleft = 0;
+ m_fupdates = 1;
+ m_dupdates = 0;
+ m_cupdates = 10;
+ m_newpairs = 1;
+ m_updates_call = 0;
+ m_updates_done = 0;
+ m_updates_ratio = 0;
+
+ m_gid = 0;
+ m_pid = 0;
+ m_cid = 0;
+ for(int i=0;i<=STAGECOUNT;++i)
+ {
+ m_stageRoots[i]=0;
+ }
+ }
+}
+
+//
+void btDbvtBroadphase::printStats()
+{}
+
+//
+#if DBVT_BP_ENABLE_BENCHMARK
+
+struct btBroadphaseBenchmark
+{
+ struct Experiment
+ {
+ const char* name;
+ int object_count;
+ int update_count;
+ int spawn_count;
+ int iterations;
+ btScalar speed;
+ btScalar amplitude;
+ };
+ struct Object
+ {
+ btVector3 center;
+ btVector3 extents;
+ btBroadphaseProxy* proxy;
+ btScalar time;
+ void update(btScalar speed,btScalar amplitude,btBroadphaseInterface* pbi)
+ {
+ time += speed;
+ center[0] = btCos(time*(btScalar)2.17)*amplitude+
+ btSin(time)*amplitude/2;
+ center[1] = btCos(time*(btScalar)1.38)*amplitude+
+ btSin(time)*amplitude;
+ center[2] = btSin(time*(btScalar)0.777)*amplitude;
+ pbi->setAabb(proxy,center-extents,center+extents,0);
+ }
+ };
+ static int UnsignedRand(int range=RAND_MAX-1) { return(rand()%(range+1)); }
+ static btScalar UnitRand() { return(UnsignedRand(16384)/(btScalar)16384); }
+ static void OutputTime(const char* name,btClock& c,unsigned count=0)
+ {
+ const unsigned long us=c.getTimeMicroseconds();
+ const unsigned long ms=(us+500)/1000;
+ const btScalar sec=us/(btScalar)(1000*1000);
+ if(count>0)
+ printf("%s : %u us (%u ms), %.2f/s\r\n",name,us,ms,count/sec);
+ else
+ printf("%s : %u us (%u ms)\r\n",name,us,ms);
+ }
+};
+
+void btDbvtBroadphase::benchmark(btBroadphaseInterface* pbi)
+{
+ static const btBroadphaseBenchmark::Experiment experiments[]=
+ {
+ {"1024o.10%",1024,10,0,8192,(btScalar)0.005,(btScalar)100},
+ /*{"4096o.10%",4096,10,0,8192,(btScalar)0.005,(btScalar)100},
+ {"8192o.10%",8192,10,0,8192,(btScalar)0.005,(btScalar)100},*/
+ };
+ static const int nexperiments=sizeof(experiments)/sizeof(experiments[0]);
+ btAlignedObjectArray objects;
+ btClock wallclock;
+ /* Begin */
+ for(int iexp=0;iexpcenter[0]=btBroadphaseBenchmark::UnitRand()*50;
+ po->center[1]=btBroadphaseBenchmark::UnitRand()*50;
+ po->center[2]=btBroadphaseBenchmark::UnitRand()*50;
+ po->extents[0]=btBroadphaseBenchmark::UnitRand()*2+2;
+ po->extents[1]=btBroadphaseBenchmark::UnitRand()*2+2;
+ po->extents[2]=btBroadphaseBenchmark::UnitRand()*2+2;
+ po->time=btBroadphaseBenchmark::UnitRand()*2000;
+ po->proxy=pbi->createProxy(po->center-po->extents,po->center+po->extents,0,po,1,1,0,0);
+ objects.push_back(po);
+ }
+ btBroadphaseBenchmark::OutputTime("\tInitialization",wallclock);
+ /* First update */
+ wallclock.reset();
+ for(int i=0;iupdate(speed,amplitude,pbi);
+ }
+ btBroadphaseBenchmark::OutputTime("\tFirst update",wallclock);
+ /* Updates */
+ wallclock.reset();
+ for(int i=0;iupdate(speed,amplitude,pbi);
+ }
+ pbi->calculateOverlappingPairs(0);
+ }
+ btBroadphaseBenchmark::OutputTime("\tUpdate",wallclock,experiment.iterations);
+ /* Clean up */
+ wallclock.reset();
+ for(int i=0;idestroyProxy(objects[i]->proxy,0);
+ delete objects[i];
+ }
+ objects.resize(0);
+ btBroadphaseBenchmark::OutputTime("\tRelease",wallclock);
+ }
+
+}
+#else
+void btDbvtBroadphase::benchmark(btBroadphaseInterface*)
+{}
+#endif
+
+#if DBVT_BP_PROFILE
+#undef SPC
+#endif
+
diff --git a/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h
new file mode 100644
index 00000000..18b64ad0
--- /dev/null
+++ b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h
@@ -0,0 +1,146 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+///btDbvtBroadphase implementation by Nathanael Presson
+#ifndef BT_DBVT_BROADPHASE_H
+#define BT_DBVT_BROADPHASE_H
+
+#include "BulletCollision/BroadphaseCollision/btDbvt.h"
+#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
+
+//
+// Compile time config
+//
+
+#define DBVT_BP_PROFILE 0
+//#define DBVT_BP_SORTPAIRS 1
+#define DBVT_BP_PREVENTFALSEUPDATE 0
+#define DBVT_BP_ACCURATESLEEPING 0
+#define DBVT_BP_ENABLE_BENCHMARK 0
+#define DBVT_BP_MARGIN (btScalar)0.05
+
+#if DBVT_BP_PROFILE
+#define DBVT_BP_PROFILING_RATE 256
+#include "LinearMath/btQuickprof.h"
+#endif
+
+//
+// btDbvtProxy
+//
+struct btDbvtProxy : btBroadphaseProxy
+{
+ /* Fields */
+ //btDbvtAabbMm aabb;
+ btDbvtNode* leaf;
+ btDbvtProxy* links[2];
+ int stage;
+ /* ctor */
+ btDbvtProxy(const btVector3& aabbMin,const btVector3& aabbMax,void* userPtr,short int collisionFilterGroup, short int collisionFilterMask) :
+ btBroadphaseProxy(aabbMin,aabbMax,userPtr,collisionFilterGroup,collisionFilterMask)
+ {
+ links[0]=links[1]=0;
+ }
+};
+
+typedef btAlignedObjectArray btDbvtProxyArray;
+
+///The btDbvtBroadphase implements a broadphase using two dynamic AABB bounding volume hierarchies/trees (see btDbvt).
+///One tree is used for static/non-moving objects, and another tree is used for dynamic objects. Objects can move from one tree to the other.
+///This is a very fast broadphase, especially for very dynamic worlds where many objects are moving. Its insert/add and remove of objects is generally faster than the sweep and prune broadphases btAxisSweep3 and bt32BitAxisSweep3.
+struct btDbvtBroadphase : btBroadphaseInterface
+{
+ /* Config */
+ enum {
+ DYNAMIC_SET = 0, /* Dynamic set index */
+ FIXED_SET = 1, /* Fixed set index */
+ STAGECOUNT = 2 /* Number of stages */
+ };
+ /* Fields */
+ btDbvt m_sets[2]; // Dbvt sets
+ btDbvtProxy* m_stageRoots[STAGECOUNT+1]; // Stages list
+ btOverlappingPairCache* m_paircache; // Pair cache
+ btScalar m_prediction; // Velocity prediction
+ int m_stageCurrent; // Current stage
+ int m_fupdates; // % of fixed updates per frame
+ int m_dupdates; // % of dynamic updates per frame
+ int m_cupdates; // % of cleanup updates per frame
+ int m_newpairs; // Number of pairs created
+ int m_fixedleft; // Fixed optimization left
+ unsigned m_updates_call; // Number of updates call
+ unsigned m_updates_done; // Number of updates done
+ btScalar m_updates_ratio; // m_updates_done/m_updates_call
+ int m_pid; // Parse id
+ int m_cid; // Cleanup index
+ int m_gid; // Gen id
+ bool m_releasepaircache; // Release pair cache on delete
+ bool m_deferedcollide; // Defere dynamic/static collision to collide call
+ bool m_needcleanup; // Need to run cleanup?
+#if DBVT_BP_PROFILE
+ btClock m_clock;
+ struct {
+ unsigned long m_total;
+ unsigned long m_ddcollide;
+ unsigned long m_fdcollide;
+ unsigned long m_cleanup;
+ unsigned long m_jobcount;
+ } m_profiling;
+#endif
+ /* Methods */
+ btDbvtBroadphase(btOverlappingPairCache* paircache=0);
+ ~btDbvtBroadphase();
+ void collide(btDispatcher* dispatcher);
+ void optimize();
+
+ /* btBroadphaseInterface Implementation */
+ btBroadphaseProxy* createProxy(const btVector3& aabbMin,const btVector3& aabbMax,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy);
+ virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+ virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher);
+ virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0), const btVector3& aabbMax = btVector3(0,0,0));
+ virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback);
+
+ virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const;
+ virtual void calculateOverlappingPairs(btDispatcher* dispatcher);
+ virtual btOverlappingPairCache* getOverlappingPairCache();
+ virtual const btOverlappingPairCache* getOverlappingPairCache() const;
+ virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const;
+ virtual void printStats();
+
+
+ ///reset broadphase internal structures, to ensure determinism/reproducability
+ virtual void resetPool(btDispatcher* dispatcher);
+
+ void performDeferredRemoval(btDispatcher* dispatcher);
+
+ void setVelocityPrediction(btScalar prediction)
+ {
+ m_prediction = prediction;
+ }
+ btScalar getVelocityPrediction() const
+ {
+ return m_prediction;
+ }
+
+ ///this setAabbForceUpdate is similar to setAabb but always forces the aabb update.
+ ///it is not part of the btBroadphaseInterface but specific to btDbvtBroadphase.
+ ///it bypasses certain optimizations that prevent aabb updates (when the aabb shrinks), see
+ ///http://code.google.com/p/bullet/issues/detail?id=223
+ void setAabbForceUpdate( btBroadphaseProxy* absproxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* /*dispatcher*/);
+
+ static void benchmark(btBroadphaseInterface*);
+
+
+};
+
+#endif
diff --git a/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btDispatcher.cpp b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btDispatcher.cpp
new file mode 100644
index 00000000..20768225
--- /dev/null
+++ b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btDispatcher.cpp
@@ -0,0 +1,22 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btDispatcher.h"
+
+btDispatcher::~btDispatcher()
+{
+
+}
+
diff --git a/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btDispatcher.h b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btDispatcher.h
new file mode 100644
index 00000000..89c307d1
--- /dev/null
+++ b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btDispatcher.h
@@ -0,0 +1,107 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_DISPATCHER_H
+#define BT_DISPATCHER_H
+#include "LinearMath/btScalar.h"
+
+class btCollisionAlgorithm;
+struct btBroadphaseProxy;
+class btRigidBody;
+class btCollisionObject;
+class btOverlappingPairCache;
+struct btCollisionObjectWrapper;
+
+class btPersistentManifold;
+class btPoolAllocator;
+
+struct btDispatcherInfo
+{
+ enum DispatchFunc
+ {
+ DISPATCH_DISCRETE = 1,
+ DISPATCH_CONTINUOUS
+ };
+ btDispatcherInfo()
+ :m_timeStep(btScalar(0.)),
+ m_stepCount(0),
+ m_dispatchFunc(DISPATCH_DISCRETE),
+ m_timeOfImpact(btScalar(1.)),
+ m_useContinuous(true),
+ m_debugDraw(0),
+ m_enableSatConvex(false),
+ m_enableSPU(true),
+ m_useEpa(true),
+ m_allowedCcdPenetration(btScalar(0.04)),
+ m_useConvexConservativeDistanceUtil(false),
+ m_convexConservativeDistanceThreshold(0.0f)
+ {
+
+ }
+ btScalar m_timeStep;
+ int m_stepCount;
+ int m_dispatchFunc;
+ mutable btScalar m_timeOfImpact;
+ bool m_useContinuous;
+ class btIDebugDraw* m_debugDraw;
+ bool m_enableSatConvex;
+ bool m_enableSPU;
+ bool m_useEpa;
+ btScalar m_allowedCcdPenetration;
+ bool m_useConvexConservativeDistanceUtil;
+ btScalar m_convexConservativeDistanceThreshold;
+};
+
+///The btDispatcher interface class can be used in combination with broadphase to dispatch calculations for overlapping pairs.
+///For example for pairwise collision detection, calculating contact points stored in btPersistentManifold or user callbacks (game logic).
+class btDispatcher
+{
+
+
+public:
+ virtual ~btDispatcher() ;
+
+ virtual btCollisionAlgorithm* findAlgorithm(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap,btPersistentManifold* sharedManifold=0) = 0;
+
+ virtual btPersistentManifold* getNewManifold(const btCollisionObject* b0,const btCollisionObject* b1)=0;
+
+ virtual void releaseManifold(btPersistentManifold* manifold)=0;
+
+ virtual void clearManifold(btPersistentManifold* manifold)=0;
+
+ virtual bool needsCollision(const btCollisionObject* body0,const btCollisionObject* body1) = 0;
+
+ virtual bool needsResponse(const btCollisionObject* body0,const btCollisionObject* body1)=0;
+
+ virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) =0;
+
+ virtual int getNumManifolds() const = 0;
+
+ virtual btPersistentManifold* getManifoldByIndexInternal(int index) = 0;
+
+ virtual btPersistentManifold** getInternalManifoldPointer() = 0;
+
+ virtual btPoolAllocator* getInternalManifoldPool() = 0;
+
+ virtual const btPoolAllocator* getInternalManifoldPool() const = 0;
+
+ virtual void* allocateCollisionAlgorithm(int size) = 0;
+
+ virtual void freeCollisionAlgorithm(void* ptr) = 0;
+
+};
+
+
+#endif //BT_DISPATCHER_H
diff --git a/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp
new file mode 100644
index 00000000..81369fe9
--- /dev/null
+++ b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp
@@ -0,0 +1,489 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btMultiSapBroadphase.h"
+
+#include "btSimpleBroadphase.h"
+#include "LinearMath/btAabbUtil2.h"
+#include "btQuantizedBvh.h"
+
+/// btSapBroadphaseArray m_sapBroadphases;
+
+/// btOverlappingPairCache* m_overlappingPairs;
+extern int gOverlappingPairs;
+
+/*
+class btMultiSapSortedOverlappingPairCache : public btSortedOverlappingPairCache
+{
+public:
+
+ virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
+ {
+ return btSortedOverlappingPairCache::addOverlappingPair((btBroadphaseProxy*)proxy0->m_multiSapParentProxy,(btBroadphaseProxy*)proxy1->m_multiSapParentProxy);
+ }
+};
+
+*/
+
+btMultiSapBroadphase::btMultiSapBroadphase(int /*maxProxies*/,btOverlappingPairCache* pairCache)
+:m_overlappingPairs(pairCache),
+m_optimizedAabbTree(0),
+m_ownsPairCache(false),
+m_invalidPair(0)
+{
+ if (!m_overlappingPairs)
+ {
+ m_ownsPairCache = true;
+ void* mem = btAlignedAlloc(sizeof(btSortedOverlappingPairCache),16);
+ m_overlappingPairs = new (mem)btSortedOverlappingPairCache();
+ }
+
+ struct btMultiSapOverlapFilterCallback : public btOverlapFilterCallback
+ {
+ virtual ~btMultiSapOverlapFilterCallback()
+ {}
+ // return true when pairs need collision
+ virtual bool needBroadphaseCollision(btBroadphaseProxy* childProxy0,btBroadphaseProxy* childProxy1) const
+ {
+ btBroadphaseProxy* multiProxy0 = (btBroadphaseProxy*)childProxy0->m_multiSapParentProxy;
+ btBroadphaseProxy* multiProxy1 = (btBroadphaseProxy*)childProxy1->m_multiSapParentProxy;
+
+ bool collides = (multiProxy0->m_collisionFilterGroup & multiProxy1->m_collisionFilterMask) != 0;
+ collides = collides && (multiProxy1->m_collisionFilterGroup & multiProxy0->m_collisionFilterMask);
+
+ return collides;
+ }
+ };
+
+ void* mem = btAlignedAlloc(sizeof(btMultiSapOverlapFilterCallback),16);
+ m_filterCallback = new (mem)btMultiSapOverlapFilterCallback();
+
+ m_overlappingPairs->setOverlapFilterCallback(m_filterCallback);
+// mem = btAlignedAlloc(sizeof(btSimpleBroadphase),16);
+// m_simpleBroadphase = new (mem) btSimpleBroadphase(maxProxies,m_overlappingPairs);
+}
+
+btMultiSapBroadphase::~btMultiSapBroadphase()
+{
+ if (m_ownsPairCache)
+ {
+ m_overlappingPairs->~btOverlappingPairCache();
+ btAlignedFree(m_overlappingPairs);
+ }
+}
+
+
+void btMultiSapBroadphase::buildTree(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax)
+{
+ m_optimizedAabbTree = new btQuantizedBvh();
+ m_optimizedAabbTree->setQuantizationValues(bvhAabbMin,bvhAabbMax);
+ QuantizedNodeArray& nodes = m_optimizedAabbTree->getLeafNodeArray();
+ for (int i=0;igetBroadphaseAabb(aabbMin,aabbMax);
+ m_optimizedAabbTree->quantize(&node.m_quantizedAabbMin[0],aabbMin,0);
+ m_optimizedAabbTree->quantize(&node.m_quantizedAabbMax[0],aabbMax,1);
+ int partId = 0;
+ node.m_escapeIndexOrTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | i;
+ nodes.push_back(node);
+ }
+ m_optimizedAabbTree->buildInternal();
+}
+
+btBroadphaseProxy* btMultiSapBroadphase::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* /*ignoreMe*/)
+{
+ //void* ignoreMe -> we could think of recursive multi-sap, if someone is interested
+
+ void* mem = btAlignedAlloc(sizeof(btMultiSapProxy),16);
+ btMultiSapProxy* proxy = new (mem)btMultiSapProxy(aabbMin, aabbMax,shapeType,userPtr, collisionFilterGroup,collisionFilterMask);
+ m_multiSapProxies.push_back(proxy);
+
+ ///this should deal with inserting/removal into child broadphases
+ setAabb(proxy,aabbMin,aabbMax,dispatcher);
+ return proxy;
+}
+
+void btMultiSapBroadphase::destroyProxy(btBroadphaseProxy* /*proxy*/,btDispatcher* /*dispatcher*/)
+{
+ ///not yet
+ btAssert(0);
+
+}
+
+
+void btMultiSapBroadphase::addToChildBroadphase(btMultiSapProxy* parentMultiSapProxy, btBroadphaseProxy* childProxy, btBroadphaseInterface* childBroadphase)
+{
+ void* mem = btAlignedAlloc(sizeof(btBridgeProxy),16);
+ btBridgeProxy* bridgeProxyRef = new(mem) btBridgeProxy;
+ bridgeProxyRef->m_childProxy = childProxy;
+ bridgeProxyRef->m_childBroadphase = childBroadphase;
+ parentMultiSapProxy->m_bridgeProxies.push_back(bridgeProxyRef);
+}
+
+
+bool boxIsContainedWithinBox(const btVector3& amin,const btVector3& amax,const btVector3& bmin,const btVector3& bmax);
+bool boxIsContainedWithinBox(const btVector3& amin,const btVector3& amax,const btVector3& bmin,const btVector3& bmax)
+{
+return
+amin.getX() >= bmin.getX() && amax.getX() <= bmax.getX() &&
+amin.getY() >= bmin.getY() && amax.getY() <= bmax.getY() &&
+amin.getZ() >= bmin.getZ() && amax.getZ() <= bmax.getZ();
+}
+
+
+
+
+
+
+void btMultiSapBroadphase::getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const
+{
+ btMultiSapProxy* multiProxy = static_cast(proxy);
+ aabbMin = multiProxy->m_aabbMin;
+ aabbMax = multiProxy->m_aabbMax;
+}
+
+void btMultiSapBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin,const btVector3& aabbMax)
+{
+ for (int i=0;i
+
+void btMultiSapBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher)
+{
+ btMultiSapProxy* multiProxy = static_cast(proxy);
+ multiProxy->m_aabbMin = aabbMin;
+ multiProxy->m_aabbMax = aabbMax;
+
+
+// bool fullyContained = false;
+// bool alreadyInSimple = false;
+
+
+
+
+ struct MyNodeOverlapCallback : public btNodeOverlapCallback
+ {
+ btMultiSapBroadphase* m_multiSap;
+ btMultiSapProxy* m_multiProxy;
+ btDispatcher* m_dispatcher;
+
+ MyNodeOverlapCallback(btMultiSapBroadphase* multiSap,btMultiSapProxy* multiProxy,btDispatcher* dispatcher)
+ :m_multiSap(multiSap),
+ m_multiProxy(multiProxy),
+ m_dispatcher(dispatcher)
+ {
+
+ }
+
+ virtual void processNode(int /*nodeSubPart*/, int broadphaseIndex)
+ {
+ btBroadphaseInterface* childBroadphase = m_multiSap->getBroadphaseArray()[broadphaseIndex];
+
+ int containingBroadphaseIndex = -1;
+ //already found?
+ for (int i=0;im_bridgeProxies.size();i++)
+ {
+
+ if (m_multiProxy->m_bridgeProxies[i]->m_childBroadphase == childBroadphase)
+ {
+ containingBroadphaseIndex = i;
+ break;
+ }
+ }
+ if (containingBroadphaseIndex<0)
+ {
+ //add it
+ btBroadphaseProxy* childProxy = childBroadphase->createProxy(m_multiProxy->m_aabbMin,m_multiProxy->m_aabbMax,m_multiProxy->m_shapeType,m_multiProxy->m_clientObject,m_multiProxy->m_collisionFilterGroup,m_multiProxy->m_collisionFilterMask, m_dispatcher,m_multiProxy);
+ m_multiSap->addToChildBroadphase(m_multiProxy,childProxy,childBroadphase);
+
+ }
+ }
+ };
+
+ MyNodeOverlapCallback myNodeCallback(this,multiProxy,dispatcher);
+
+
+
+
+ if (m_optimizedAabbTree)
+ m_optimizedAabbTree->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax);
+
+ int i;
+
+ for ( i=0;im_bridgeProxies.size();i++)
+ {
+ btVector3 worldAabbMin,worldAabbMax;
+ multiProxy->m_bridgeProxies[i]->m_childBroadphase->getBroadphaseAabb(worldAabbMin,worldAabbMax);
+ bool overlapsBroadphase = TestAabbAgainstAabb2(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax);
+ if (!overlapsBroadphase)
+ {
+ //remove it now
+ btBridgeProxy* bridgeProxy = multiProxy->m_bridgeProxies[i];
+
+ btBroadphaseProxy* childProxy = bridgeProxy->m_childProxy;
+ bridgeProxy->m_childBroadphase->destroyProxy(childProxy,dispatcher);
+
+ multiProxy->m_bridgeProxies.swap( i,multiProxy->m_bridgeProxies.size()-1);
+ multiProxy->m_bridgeProxies.pop_back();
+
+ }
+ }
+
+
+ /*
+
+ if (1)
+ {
+
+ //find broadphase that contain this multiProxy
+ int numChildBroadphases = getBroadphaseArray().size();
+ for (int i=0;igetBroadphaseAabb(worldAabbMin,worldAabbMax);
+ bool overlapsBroadphase = TestAabbAgainstAabb2(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax);
+
+ // fullyContained = fullyContained || boxIsContainedWithinBox(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax);
+ int containingBroadphaseIndex = -1;
+
+ //if already contains this
+
+ for (int i=0;im_bridgeProxies.size();i++)
+ {
+ if (multiProxy->m_bridgeProxies[i]->m_childBroadphase == childBroadphase)
+ {
+ containingBroadphaseIndex = i;
+ }
+ alreadyInSimple = alreadyInSimple || (multiProxy->m_bridgeProxies[i]->m_childBroadphase == m_simpleBroadphase);
+ }
+
+ if (overlapsBroadphase)
+ {
+ if (containingBroadphaseIndex<0)
+ {
+ btBroadphaseProxy* childProxy = childBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher);
+ childProxy->m_multiSapParentProxy = multiProxy;
+ addToChildBroadphase(multiProxy,childProxy,childBroadphase);
+ }
+ } else
+ {
+ if (containingBroadphaseIndex>=0)
+ {
+ //remove
+ btBridgeProxy* bridgeProxy = multiProxy->m_bridgeProxies[containingBroadphaseIndex];
+
+ btBroadphaseProxy* childProxy = bridgeProxy->m_childProxy;
+ bridgeProxy->m_childBroadphase->destroyProxy(childProxy,dispatcher);
+
+ multiProxy->m_bridgeProxies.swap( containingBroadphaseIndex,multiProxy->m_bridgeProxies.size()-1);
+ multiProxy->m_bridgeProxies.pop_back();
+ }
+ }
+ }
+
+
+ ///If we are in no other child broadphase, stick the proxy in the global 'simple' broadphase (brute force)
+ ///hopefully we don't end up with many entries here (can assert/provide feedback on stats)
+ if (0)//!multiProxy->m_bridgeProxies.size())
+ {
+ ///we don't pass the userPtr but our multisap proxy. We need to patch this, before processing an actual collision
+ ///this is needed to be able to calculate the aabb overlap
+ btBroadphaseProxy* childProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher);
+ childProxy->m_multiSapParentProxy = multiProxy;
+ addToChildBroadphase(multiProxy,childProxy,m_simpleBroadphase);
+ }
+ }
+
+ if (!multiProxy->m_bridgeProxies.size())
+ {
+ ///we don't pass the userPtr but our multisap proxy. We need to patch this, before processing an actual collision
+ ///this is needed to be able to calculate the aabb overlap
+ btBroadphaseProxy* childProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher);
+ childProxy->m_multiSapParentProxy = multiProxy;
+ addToChildBroadphase(multiProxy,childProxy,m_simpleBroadphase);
+ }
+*/
+
+
+ //update
+ for ( i=0;im_bridgeProxies.size();i++)
+ {
+ btBridgeProxy* bridgeProxyRef = multiProxy->m_bridgeProxies[i];
+ bridgeProxyRef->m_childBroadphase->setAabb(bridgeProxyRef->m_childProxy,aabbMin,aabbMax,dispatcher);
+ }
+
+}
+bool stopUpdating=false;
+
+
+
+class btMultiSapBroadphasePairSortPredicate
+{
+ public:
+
+ bool operator() ( const btBroadphasePair& a1, const btBroadphasePair& b1 ) const
+ {
+ btMultiSapBroadphase::btMultiSapProxy* aProxy0 = a1.m_pProxy0 ? (btMultiSapBroadphase::btMultiSapProxy*)a1.m_pProxy0->m_multiSapParentProxy : 0;
+ btMultiSapBroadphase::btMultiSapProxy* aProxy1 = a1.m_pProxy1 ? (btMultiSapBroadphase::btMultiSapProxy*)a1.m_pProxy1->m_multiSapParentProxy : 0;
+ btMultiSapBroadphase::btMultiSapProxy* bProxy0 = b1.m_pProxy0 ? (btMultiSapBroadphase::btMultiSapProxy*)b1.m_pProxy0->m_multiSapParentProxy : 0;
+ btMultiSapBroadphase::btMultiSapProxy* bProxy1 = b1.m_pProxy1 ? (btMultiSapBroadphase::btMultiSapProxy*)b1.m_pProxy1->m_multiSapParentProxy : 0;
+
+ return aProxy0 > bProxy0 ||
+ (aProxy0 == bProxy0 && aProxy1 > bProxy1) ||
+ (aProxy0 == bProxy0 && aProxy1 == bProxy1 && a1.m_algorithm > b1.m_algorithm);
+ }
+};
+
+
+ ///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb
+void btMultiSapBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
+{
+
+// m_simpleBroadphase->calculateOverlappingPairs(dispatcher);
+
+ if (!stopUpdating && getOverlappingPairCache()->hasDeferredRemoval())
+ {
+
+ btBroadphasePairArray& overlappingPairArray = getOverlappingPairCache()->getOverlappingPairArray();
+
+ // quicksort(overlappingPairArray,0,overlappingPairArray.size());
+
+ overlappingPairArray.quickSort(btMultiSapBroadphasePairSortPredicate());
+
+ //perform a sort, to find duplicates and to sort 'invalid' pairs to the end
+ // overlappingPairArray.heapSort(btMultiSapBroadphasePairSortPredicate());
+
+ overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
+ m_invalidPair = 0;
+
+
+ int i;
+
+ btBroadphasePair previousPair;
+ previousPair.m_pProxy0 = 0;
+ previousPair.m_pProxy1 = 0;
+ previousPair.m_algorithm = 0;
+
+
+ for (i=0;im_multiSapParentProxy : 0;
+ btMultiSapProxy* aProxy1 = pair.m_pProxy1 ? (btMultiSapProxy*)pair.m_pProxy1->m_multiSapParentProxy : 0;
+ btMultiSapProxy* bProxy0 = previousPair.m_pProxy0 ? (btMultiSapProxy*)previousPair.m_pProxy0->m_multiSapParentProxy : 0;
+ btMultiSapProxy* bProxy1 = previousPair.m_pProxy1 ? (btMultiSapProxy*)previousPair.m_pProxy1->m_multiSapParentProxy : 0;
+
+ bool isDuplicate = (aProxy0 == bProxy0) && (aProxy1 == bProxy1);
+
+ previousPair = pair;
+
+ bool needsRemoval = false;
+
+ if (!isDuplicate)
+ {
+ bool hasOverlap = testAabbOverlap(pair.m_pProxy0,pair.m_pProxy1);
+
+ if (hasOverlap)
+ {
+ needsRemoval = false;//callback->processOverlap(pair);
+ } else
+ {
+ needsRemoval = true;
+ }
+ } else
+ {
+ //remove duplicate
+ needsRemoval = true;
+ //should have no algorithm
+ btAssert(!pair.m_algorithm);
+ }
+
+ if (needsRemoval)
+ {
+ getOverlappingPairCache()->cleanOverlappingPair(pair,dispatcher);
+
+ // m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
+ // m_overlappingPairArray.pop_back();
+ pair.m_pProxy0 = 0;
+ pair.m_pProxy1 = 0;
+ m_invalidPair++;
+ gOverlappingPairs--;
+ }
+
+ }
+
+ ///if you don't like to skip the invalid pairs in the array, execute following code:
+ #define CLEAN_INVALID_PAIRS 1
+ #ifdef CLEAN_INVALID_PAIRS
+
+ //perform a sort, to sort 'invalid' pairs to the end
+ //overlappingPairArray.heapSort(btMultiSapBroadphasePairSortPredicate());
+ overlappingPairArray.quickSort(btMultiSapBroadphasePairSortPredicate());
+
+ overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
+ m_invalidPair = 0;
+ #endif//CLEAN_INVALID_PAIRS
+
+ //printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size());
+ }
+
+
+}
+
+
+bool btMultiSapBroadphase::testAabbOverlap(btBroadphaseProxy* childProxy0,btBroadphaseProxy* childProxy1)
+{
+ btMultiSapProxy* multiSapProxy0 = (btMultiSapProxy*)childProxy0->m_multiSapParentProxy;
+ btMultiSapProxy* multiSapProxy1 = (btMultiSapProxy*)childProxy1->m_multiSapParentProxy;
+
+ return TestAabbAgainstAabb2(multiSapProxy0->m_aabbMin,multiSapProxy0->m_aabbMax,
+ multiSapProxy1->m_aabbMin,multiSapProxy1->m_aabbMax);
+
+}
+
+
+void btMultiSapBroadphase::printStats()
+{
+/* printf("---------------------------------\n");
+
+ printf("btMultiSapBroadphase.h\n");
+ printf("numHandles = %d\n",m_multiSapProxies.size());
+ //find broadphase that contain this multiProxy
+ int numChildBroadphases = getBroadphaseArray().size();
+ for (int i=0;iprintStats();
+
+ }
+ */
+
+}
+
+void btMultiSapBroadphase::resetPool(btDispatcher* dispatcher)
+{
+ // not yet
+}
diff --git a/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h
new file mode 100644
index 00000000..7bcfe6b1
--- /dev/null
+++ b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h
@@ -0,0 +1,151 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef BT_MULTI_SAP_BROADPHASE
+#define BT_MULTI_SAP_BROADPHASE
+
+#include "btBroadphaseInterface.h"
+#include "LinearMath/btAlignedObjectArray.h"
+#include "btOverlappingPairCache.h"
+
+
+class btBroadphaseInterface;
+class btSimpleBroadphase;
+
+
+typedef btAlignedObjectArray btSapBroadphaseArray;
+
+///The btMultiSapBroadphase is a research project, not recommended to use in production. Use btAxisSweep3 or btDbvtBroadphase instead.
+///The btMultiSapBroadphase is a broadphase that contains multiple SAP broadphases.
+///The user can add SAP broadphases that cover the world. A btBroadphaseProxy can be in multiple child broadphases at the same time.
+///A btQuantizedBvh acceleration structures finds overlapping SAPs for each btBroadphaseProxy.
+///See http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=328
+///and http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1329
+class btMultiSapBroadphase :public btBroadphaseInterface
+{
+ btSapBroadphaseArray m_sapBroadphases;
+
+ btSimpleBroadphase* m_simpleBroadphase;
+
+ btOverlappingPairCache* m_overlappingPairs;
+
+ class btQuantizedBvh* m_optimizedAabbTree;
+
+
+ bool m_ownsPairCache;
+
+ btOverlapFilterCallback* m_filterCallback;
+
+ int m_invalidPair;
+
+ struct btBridgeProxy
+ {
+ btBroadphaseProxy* m_childProxy;
+ btBroadphaseInterface* m_childBroadphase;
+ };
+
+
+public:
+
+ struct btMultiSapProxy : public btBroadphaseProxy
+ {
+
+ ///array with all the entries that this proxy belongs to
+ btAlignedObjectArray m_bridgeProxies;
+ btVector3 m_aabbMin;
+ btVector3 m_aabbMax;
+
+ int m_shapeType;
+
+/* void* m_userPtr;
+ short int m_collisionFilterGroup;
+ short int m_collisionFilterMask;
+*/
+ btMultiSapProxy(const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask)
+ :btBroadphaseProxy(aabbMin,aabbMax,userPtr,collisionFilterGroup,collisionFilterMask),
+ m_aabbMin(aabbMin),
+ m_aabbMax(aabbMax),
+ m_shapeType(shapeType)
+ {
+ m_multiSapParentProxy =this;
+ }
+
+
+ };
+
+protected:
+
+
+ btAlignedObjectArray m_multiSapProxies;
+
+public:
+
+ btMultiSapBroadphase(int maxProxies = 16384,btOverlappingPairCache* pairCache=0);
+
+
+ btSapBroadphaseArray& getBroadphaseArray()
+ {
+ return m_sapBroadphases;
+ }
+
+ const btSapBroadphaseArray& getBroadphaseArray() const
+ {
+ return m_sapBroadphases;
+ }
+
+ virtual ~btMultiSapBroadphase();
+
+ virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy);
+ virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+ virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher);
+ virtual void getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const;
+
+ virtual void rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback,const btVector3& aabbMin=btVector3(0,0,0),const btVector3& aabbMax=btVector3(0,0,0));
+
+ void addToChildBroadphase(btMultiSapProxy* parentMultiSapProxy, btBroadphaseProxy* childProxy, btBroadphaseInterface* childBroadphase);
+
+ ///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb
+ virtual void calculateOverlappingPairs(btDispatcher* dispatcher);
+
+ bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
+
+ virtual btOverlappingPairCache* getOverlappingPairCache()
+ {
+ return m_overlappingPairs;
+ }
+ virtual const btOverlappingPairCache* getOverlappingPairCache() const
+ {
+ return m_overlappingPairs;
+ }
+
+ ///getAabb returns the axis aligned bounding box in the 'global' coordinate frame
+ ///will add some transform later
+ virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const
+ {
+ aabbMin.setValue(-BT_LARGE_FLOAT,-BT_LARGE_FLOAT,-BT_LARGE_FLOAT);
+ aabbMax.setValue(BT_LARGE_FLOAT,BT_LARGE_FLOAT,BT_LARGE_FLOAT);
+ }
+
+ void buildTree(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax);
+
+ virtual void printStats();
+
+ void quicksort (btBroadphasePairArray& a, int lo, int hi);
+
+ ///reset broadphase internal structures, to ensure determinism/reproducability
+ virtual void resetPool(btDispatcher* dispatcher);
+
+};
+
+#endif //BT_MULTI_SAP_BROADPHASE
diff --git a/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp
new file mode 100644
index 00000000..ae22dadc
--- /dev/null
+++ b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp
@@ -0,0 +1,633 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#include "btOverlappingPairCache.h"
+
+#include "btDispatcher.h"
+#include "btCollisionAlgorithm.h"
+#include "LinearMath/btAabbUtil2.h"
+
+#include
+
+int gOverlappingPairs = 0;
+
+int gRemovePairs =0;
+int gAddedPairs =0;
+int gFindPairs =0;
+
+
+
+
+btHashedOverlappingPairCache::btHashedOverlappingPairCache():
+ m_overlapFilterCallback(0),
+ m_blockedForChanges(false),
+ m_ghostPairCallback(0)
+{
+ int initialAllocatedSize= 2;
+ m_overlappingPairArray.reserve(initialAllocatedSize);
+ growTables();
+}
+
+
+
+
+btHashedOverlappingPairCache::~btHashedOverlappingPairCache()
+{
+}
+
+
+
+void btHashedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher)
+{
+ if (pair.m_algorithm && dispatcher)
+ {
+ {
+ pair.m_algorithm->~btCollisionAlgorithm();
+ dispatcher->freeCollisionAlgorithm(pair.m_algorithm);
+ pair.m_algorithm=0;
+ }
+ }
+}
+
+
+
+
+void btHashedOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
+{
+
+ class CleanPairCallback : public btOverlapCallback
+ {
+ btBroadphaseProxy* m_cleanProxy;
+ btOverlappingPairCache* m_pairCache;
+ btDispatcher* m_dispatcher;
+
+ public:
+ CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache,btDispatcher* dispatcher)
+ :m_cleanProxy(cleanProxy),
+ m_pairCache(pairCache),
+ m_dispatcher(dispatcher)
+ {
+ }
+ virtual bool processOverlap(btBroadphasePair& pair)
+ {
+ if ((pair.m_pProxy0 == m_cleanProxy) ||
+ (pair.m_pProxy1 == m_cleanProxy))
+ {
+ m_pairCache->cleanOverlappingPair(pair,m_dispatcher);
+ }
+ return false;
+ }
+
+ };
+
+ CleanPairCallback cleanPairs(proxy,this,dispatcher);
+
+ processAllOverlappingPairs(&cleanPairs,dispatcher);
+
+}
+
+
+
+
+void btHashedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
+{
+
+ class RemovePairCallback : public btOverlapCallback
+ {
+ btBroadphaseProxy* m_obsoleteProxy;
+
+ public:
+ RemovePairCallback(btBroadphaseProxy* obsoleteProxy)
+ :m_obsoleteProxy(obsoleteProxy)
+ {
+ }
+ virtual bool processOverlap(btBroadphasePair& pair)
+ {
+ return ((pair.m_pProxy0 == m_obsoleteProxy) ||
+ (pair.m_pProxy1 == m_obsoleteProxy));
+ }
+
+ };
+
+
+ RemovePairCallback removeCallback(proxy);
+
+ processAllOverlappingPairs(&removeCallback,dispatcher);
+}
+
+
+
+
+
+btBroadphasePair* btHashedOverlappingPairCache::findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
+{
+ gFindPairs++;
+ if(proxy0->m_uniqueId>proxy1->m_uniqueId)
+ btSwap(proxy0,proxy1);
+ int proxyId1 = proxy0->getUid();
+ int proxyId2 = proxy1->getUid();
+
+ /*if (proxyId1 > proxyId2)
+ btSwap(proxyId1, proxyId2);*/
+
+ int hash = static_cast(getHash(static_cast(proxyId1), static_cast(proxyId2)) & (m_overlappingPairArray.capacity()-1));
+
+ if (hash >= m_hashTable.size())
+ {
+ return NULL;
+ }
+
+ int index = m_hashTable[hash];
+ while (index != BT_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false)
+ {
+ index = m_next[index];
+ }
+
+ if (index == BT_NULL_PAIR)
+ {
+ return NULL;
+ }
+
+ btAssert(index < m_overlappingPairArray.size());
+
+ return &m_overlappingPairArray[index];
+}
+
+//#include
+
+void btHashedOverlappingPairCache::growTables()
+{
+
+ int newCapacity = m_overlappingPairArray.capacity();
+
+ if (m_hashTable.size() < newCapacity)
+ {
+ //grow hashtable and next table
+ int curHashtableSize = m_hashTable.size();
+
+ m_hashTable.resize(newCapacity);
+ m_next.resize(newCapacity);
+
+
+ int i;
+
+ for (i= 0; i < newCapacity; ++i)
+ {
+ m_hashTable[i] = BT_NULL_PAIR;
+ }
+ for (i = 0; i < newCapacity; ++i)
+ {
+ m_next[i] = BT_NULL_PAIR;
+ }
+
+ for(i=0;igetUid();
+ int proxyId2 = pair.m_pProxy1->getUid();
+ /*if (proxyId1 > proxyId2)
+ btSwap(proxyId1, proxyId2);*/
+ int hashValue = static_cast(getHash(static_cast(proxyId1),static_cast(proxyId2)) & (m_overlappingPairArray.capacity()-1)); // New hash value with new mask
+ m_next[i] = m_hashTable[hashValue];
+ m_hashTable[hashValue] = i;
+ }
+
+
+ }
+}
+
+btBroadphasePair* btHashedOverlappingPairCache::internalAddPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
+{
+ if(proxy0->m_uniqueId>proxy1->m_uniqueId)
+ btSwap(proxy0,proxy1);
+ int proxyId1 = proxy0->getUid();
+ int proxyId2 = proxy1->getUid();
+
+ /*if (proxyId1 > proxyId2)
+ btSwap(proxyId1, proxyId2);*/
+
+ int hash = static_cast(getHash(static_cast(proxyId1),static_cast(proxyId2)) & (m_overlappingPairArray.capacity()-1)); // New hash value with new mask
+
+
+ btBroadphasePair* pair = internalFindPair(proxy0, proxy1, hash);
+ if (pair != NULL)
+ {
+ return pair;
+ }
+ /*for(int i=0;i%u\r\n",proxyId1,proxyId2);
+ internalFindPair(proxy0, proxy1, hash);
+ }
+ }*/
+ int count = m_overlappingPairArray.size();
+ int oldCapacity = m_overlappingPairArray.capacity();
+ void* mem = &m_overlappingPairArray.expandNonInitializing();
+
+ //this is where we add an actual pair, so also call the 'ghost'
+ if (m_ghostPairCallback)
+ m_ghostPairCallback->addOverlappingPair(proxy0,proxy1);
+
+ int newCapacity = m_overlappingPairArray.capacity();
+
+ if (oldCapacity < newCapacity)
+ {
+ growTables();
+ //hash with new capacity
+ hash = static_cast(getHash(static_cast(proxyId1),static_cast(proxyId2)) & (m_overlappingPairArray.capacity()-1));
+ }
+
+ pair = new (mem) btBroadphasePair(*proxy0,*proxy1);
+// pair->m_pProxy0 = proxy0;
+// pair->m_pProxy1 = proxy1;
+ pair->m_algorithm = 0;
+ pair->m_internalTmpValue = 0;
+
+
+ m_next[count] = m_hashTable[hash];
+ m_hashTable[hash] = count;
+
+ return pair;
+}
+
+
+
+void* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1,btDispatcher* dispatcher)
+{
+ gRemovePairs++;
+ if(proxy0->m_uniqueId>proxy1->m_uniqueId)
+ btSwap(proxy0,proxy1);
+ int proxyId1 = proxy0->getUid();
+ int proxyId2 = proxy1->getUid();
+
+ /*if (proxyId1 > proxyId2)
+ btSwap(proxyId1, proxyId2);*/
+
+ int hash = static_cast(getHash(static_cast(proxyId1),static_cast(proxyId2)) & (m_overlappingPairArray.capacity()-1));
+
+ btBroadphasePair* pair = internalFindPair(proxy0, proxy1, hash);
+ if (pair == NULL)
+ {
+ return 0;
+ }
+
+ cleanOverlappingPair(*pair,dispatcher);
+
+ void* userData = pair->m_internalInfo1;
+
+ btAssert(pair->m_pProxy0->getUid() == proxyId1);
+ btAssert(pair->m_pProxy1->getUid() == proxyId2);
+
+ int pairIndex = int(pair - &m_overlappingPairArray[0]);
+ btAssert(pairIndex < m_overlappingPairArray.size());
+
+ // Remove the pair from the hash table.
+ int index = m_hashTable[hash];
+ btAssert(index != BT_NULL_PAIR);
+
+ int previous = BT_NULL_PAIR;
+ while (index != pairIndex)
+ {
+ previous = index;
+ index = m_next[index];
+ }
+
+ if (previous != BT_NULL_PAIR)
+ {
+ btAssert(m_next[previous] == pairIndex);
+ m_next[previous] = m_next[pairIndex];
+ }
+ else
+ {
+ m_hashTable[hash] = m_next[pairIndex];
+ }
+
+ // We now move the last pair into spot of the
+ // pair being removed. We need to fix the hash
+ // table indices to support the move.
+
+ int lastPairIndex = m_overlappingPairArray.size() - 1;
+
+ if (m_ghostPairCallback)
+ m_ghostPairCallback->removeOverlappingPair(proxy0, proxy1,dispatcher);
+
+ // If the removed pair is the last pair, we are done.
+ if (lastPairIndex == pairIndex)
+ {
+ m_overlappingPairArray.pop_back();
+ return userData;
+ }
+
+ // Remove the last pair from the hash table.
+ const btBroadphasePair* last = &m_overlappingPairArray[lastPairIndex];
+ /* missing swap here too, Nat. */
+ int lastHash = static_cast(getHash(static_cast(last->m_pProxy0->getUid()), static_cast(last->m_pProxy1->getUid())) & (m_overlappingPairArray.capacity()-1));
+
+ index = m_hashTable[lastHash];
+ btAssert(index != BT_NULL_PAIR);
+
+ previous = BT_NULL_PAIR;
+ while (index != lastPairIndex)
+ {
+ previous = index;
+ index = m_next[index];
+ }
+
+ if (previous != BT_NULL_PAIR)
+ {
+ btAssert(m_next[previous] == lastPairIndex);
+ m_next[previous] = m_next[lastPairIndex];
+ }
+ else
+ {
+ m_hashTable[lastHash] = m_next[lastPairIndex];
+ }
+
+ // Copy the last pair into the remove pair's spot.
+ m_overlappingPairArray[pairIndex] = m_overlappingPairArray[lastPairIndex];
+
+ // Insert the last pair into the hash table
+ m_next[pairIndex] = m_hashTable[lastHash];
+ m_hashTable[lastHash] = pairIndex;
+
+ m_overlappingPairArray.pop_back();
+
+ return userData;
+}
+//#include
+
+void btHashedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher)
+{
+
+ int i;
+
+// printf("m_overlappingPairArray.size()=%d\n",m_overlappingPairArray.size());
+ for (i=0;iprocessOverlap(*pair))
+ {
+ removeOverlappingPair(pair->m_pProxy0,pair->m_pProxy1,dispatcher);
+
+ gOverlappingPairs--;
+ } else
+ {
+ i++;
+ }
+ }
+}
+
+void btHashedOverlappingPairCache::sortOverlappingPairs(btDispatcher* dispatcher)
+{
+ ///need to keep hashmap in sync with pair address, so rebuild all
+ btBroadphasePairArray tmpPairs;
+ int i;
+ for (i=0;iremoveOverlappingPair(proxy0, proxy1,dispatcher);
+
+ m_overlappingPairArray.swap(findIndex,m_overlappingPairArray.capacity()-1);
+ m_overlappingPairArray.pop_back();
+ return userData;
+ }
+ }
+
+ return 0;
+}
+
+
+
+
+
+
+
+
+btBroadphasePair* btSortedOverlappingPairCache::addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
+{
+ //don't add overlap with own
+ btAssert(proxy0 != proxy1);
+
+ if (!needsBroadphaseCollision(proxy0,proxy1))
+ return 0;
+
+ void* mem = &m_overlappingPairArray.expandNonInitializing();
+ btBroadphasePair* pair = new (mem) btBroadphasePair(*proxy0,*proxy1);
+
+ gOverlappingPairs++;
+ gAddedPairs++;
+
+ if (m_ghostPairCallback)
+ m_ghostPairCallback->addOverlappingPair(proxy0, proxy1);
+ return pair;
+
+}
+
+///this findPair becomes really slow. Either sort the list to speedup the query, or
+///use a different solution. It is mainly used for Removing overlapping pairs. Removal could be delayed.
+///we could keep a linked list in each proxy, and store pair in one of the proxies (with lowest memory address)
+///Also we can use a 2D bitmap, which can be useful for a future GPU implementation
+ btBroadphasePair* btSortedOverlappingPairCache::findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
+{
+ if (!needsBroadphaseCollision(proxy0,proxy1))
+ return 0;
+
+ btBroadphasePair tmpPair(*proxy0,*proxy1);
+ int findIndex = m_overlappingPairArray.findLinearSearch(tmpPair);
+
+ if (findIndex < m_overlappingPairArray.size())
+ {
+ //btAssert(it != m_overlappingPairSet.end());
+ btBroadphasePair* pair = &m_overlappingPairArray[findIndex];
+ return pair;
+ }
+ return 0;
+}
+
+
+
+
+
+
+
+
+
+
+//#include
+
+void btSortedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher)
+{
+
+ int i;
+
+ for (i=0;iprocessOverlap(*pair))
+ {
+ cleanOverlappingPair(*pair,dispatcher);
+ pair->m_pProxy0 = 0;
+ pair->m_pProxy1 = 0;
+ m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
+ m_overlappingPairArray.pop_back();
+ gOverlappingPairs--;
+ } else
+ {
+ i++;
+ }
+ }
+}
+
+
+
+
+btSortedOverlappingPairCache::btSortedOverlappingPairCache():
+ m_blockedForChanges(false),
+ m_hasDeferredRemoval(true),
+ m_overlapFilterCallback(0),
+ m_ghostPairCallback(0)
+{
+ int initialAllocatedSize= 2;
+ m_overlappingPairArray.reserve(initialAllocatedSize);
+}
+
+btSortedOverlappingPairCache::~btSortedOverlappingPairCache()
+{
+}
+
+void btSortedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher)
+{
+ if (pair.m_algorithm)
+ {
+ {
+ pair.m_algorithm->~btCollisionAlgorithm();
+ dispatcher->freeCollisionAlgorithm(pair.m_algorithm);
+ pair.m_algorithm=0;
+ gRemovePairs--;
+ }
+ }
+}
+
+
+void btSortedOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
+{
+
+ class CleanPairCallback : public btOverlapCallback
+ {
+ btBroadphaseProxy* m_cleanProxy;
+ btOverlappingPairCache* m_pairCache;
+ btDispatcher* m_dispatcher;
+
+ public:
+ CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache,btDispatcher* dispatcher)
+ :m_cleanProxy(cleanProxy),
+ m_pairCache(pairCache),
+ m_dispatcher(dispatcher)
+ {
+ }
+ virtual bool processOverlap(btBroadphasePair& pair)
+ {
+ if ((pair.m_pProxy0 == m_cleanProxy) ||
+ (pair.m_pProxy1 == m_cleanProxy))
+ {
+ m_pairCache->cleanOverlappingPair(pair,m_dispatcher);
+ }
+ return false;
+ }
+
+ };
+
+ CleanPairCallback cleanPairs(proxy,this,dispatcher);
+
+ processAllOverlappingPairs(&cleanPairs,dispatcher);
+
+}
+
+
+void btSortedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
+{
+
+ class RemovePairCallback : public btOverlapCallback
+ {
+ btBroadphaseProxy* m_obsoleteProxy;
+
+ public:
+ RemovePairCallback(btBroadphaseProxy* obsoleteProxy)
+ :m_obsoleteProxy(obsoleteProxy)
+ {
+ }
+ virtual bool processOverlap(btBroadphasePair& pair)
+ {
+ return ((pair.m_pProxy0 == m_obsoleteProxy) ||
+ (pair.m_pProxy1 == m_obsoleteProxy));
+ }
+
+ };
+
+ RemovePairCallback removeCallback(proxy);
+
+ processAllOverlappingPairs(&removeCallback,dispatcher);
+}
+
+void btSortedOverlappingPairCache::sortOverlappingPairs(btDispatcher* dispatcher)
+{
+ //should already be sorted
+}
+
diff --git a/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h
new file mode 100644
index 00000000..eee90e47
--- /dev/null
+++ b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h
@@ -0,0 +1,470 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_OVERLAPPING_PAIR_CACHE_H
+#define BT_OVERLAPPING_PAIR_CACHE_H
+
+
+#include "btBroadphaseInterface.h"
+#include "btBroadphaseProxy.h"
+#include "btOverlappingPairCallback.h"
+
+#include "LinearMath/btAlignedObjectArray.h"
+class btDispatcher;
+
+typedef btAlignedObjectArray btBroadphasePairArray;
+
+struct btOverlapCallback
+{
+ virtual ~btOverlapCallback()
+ {}
+ //return true for deletion of the pair
+ virtual bool processOverlap(btBroadphasePair& pair) = 0;
+
+};
+
+struct btOverlapFilterCallback
+{
+ virtual ~btOverlapFilterCallback()
+ {}
+ // return true when pairs need collision
+ virtual bool needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const = 0;
+};
+
+
+
+
+
+
+
+extern int gRemovePairs;
+extern int gAddedPairs;
+extern int gFindPairs;
+
+const int BT_NULL_PAIR=0xffffffff;
+
+///The btOverlappingPairCache provides an interface for overlapping pair management (add, remove, storage), used by the btBroadphaseInterface broadphases.
+///The btHashedOverlappingPairCache and btSortedOverlappingPairCache classes are two implementations.
+class btOverlappingPairCache : public btOverlappingPairCallback
+{
+public:
+ virtual ~btOverlappingPairCache() {} // this is needed so we can get to the derived class destructor
+
+ virtual btBroadphasePair* getOverlappingPairArrayPtr() = 0;
+
+ virtual const btBroadphasePair* getOverlappingPairArrayPtr() const = 0;
+
+ virtual btBroadphasePairArray& getOverlappingPairArray() = 0;
+
+ virtual void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher) = 0;
+
+ virtual int getNumOverlappingPairs() const = 0;
+
+ virtual void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher) = 0;
+
+ virtual void setOverlapFilterCallback(btOverlapFilterCallback* callback) = 0;
+
+ virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher) = 0;
+
+ virtual btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) = 0;
+
+ virtual bool hasDeferredRemoval() = 0;
+
+ virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)=0;
+
+ virtual void sortOverlappingPairs(btDispatcher* dispatcher) = 0;
+
+
+};
+
+/// Hash-space based Pair Cache, thanks to Erin Catto, Box2D, http://www.box2d.org, and Pierre Terdiman, Codercorner, http://codercorner.com
+class btHashedOverlappingPairCache : public btOverlappingPairCache
+{
+ btBroadphasePairArray m_overlappingPairArray;
+ btOverlapFilterCallback* m_overlapFilterCallback;
+ bool m_blockedForChanges;
+
+protected:
+
+ btAlignedObjectArray m_hashTable;
+ btAlignedObjectArray m_next;
+ btOverlappingPairCallback* m_ghostPairCallback;
+
+
+public:
+ btHashedOverlappingPairCache();
+ virtual ~btHashedOverlappingPairCache();
+
+
+ void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+
+ virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher);
+
+ SIMD_FORCE_INLINE bool needsBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const
+ {
+ if (m_overlapFilterCallback)
+ return m_overlapFilterCallback->needBroadphaseCollision(proxy0,proxy1);
+
+ bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
+ collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
+
+ return collides;
+ }
+
+ // Add a pair and return the new pair. If the pair already exists,
+ // no new pair is created and the old one is returned.
+ virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
+ {
+ gAddedPairs++;
+
+ if (!needsBroadphaseCollision(proxy0,proxy1))
+ return 0;
+
+ return internalAddPair(proxy0,proxy1);
+ }
+
+
+
+ void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+
+
+ virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher);
+
+ virtual btBroadphasePair* getOverlappingPairArrayPtr()
+ {
+ return &m_overlappingPairArray[0];
+ }
+
+ const btBroadphasePair* getOverlappingPairArrayPtr() const
+ {
+ return &m_overlappingPairArray[0];
+ }
+
+ btBroadphasePairArray& getOverlappingPairArray()
+ {
+ return m_overlappingPairArray;
+ }
+
+ const btBroadphasePairArray& getOverlappingPairArray() const
+ {
+ return m_overlappingPairArray;
+ }
+
+ void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher);
+
+
+
+ btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1);
+
+ int GetCount() const { return m_overlappingPairArray.size(); }
+// btBroadphasePair* GetPairs() { return m_pairs; }
+
+ btOverlapFilterCallback* getOverlapFilterCallback()
+ {
+ return m_overlapFilterCallback;
+ }
+
+ void setOverlapFilterCallback(btOverlapFilterCallback* callback)
+ {
+ m_overlapFilterCallback = callback;
+ }
+
+ int getNumOverlappingPairs() const
+ {
+ return m_overlappingPairArray.size();
+ }
+private:
+
+ btBroadphasePair* internalAddPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
+
+ void growTables();
+
+ SIMD_FORCE_INLINE bool equalsPair(const btBroadphasePair& pair, int proxyId1, int proxyId2)
+ {
+ return pair.m_pProxy0->getUid() == proxyId1 && pair.m_pProxy1->getUid() == proxyId2;
+ }
+
+ /*
+ // Thomas Wang's hash, see: http://www.concentric.net/~Ttwang/tech/inthash.htm
+ // This assumes proxyId1 and proxyId2 are 16-bit.
+ SIMD_FORCE_INLINE int getHash(int proxyId1, int proxyId2)
+ {
+ int key = (proxyId2 << 16) | proxyId1;
+ key = ~key + (key << 15);
+ key = key ^ (key >> 12);
+ key = key + (key << 2);
+ key = key ^ (key >> 4);
+ key = key * 2057;
+ key = key ^ (key >> 16);
+ return key;
+ }
+ */
+
+
+
+ SIMD_FORCE_INLINE unsigned int getHash(unsigned int proxyId1, unsigned int proxyId2)
+ {
+ int key = static_cast(((unsigned int)proxyId1) | (((unsigned int)proxyId2) <<16));
+ // Thomas Wang's hash
+
+ key += ~(key << 15);
+ key ^= (key >> 10);
+ key += (key << 3);
+ key ^= (key >> 6);
+ key += ~(key << 11);
+ key ^= (key >> 16);
+ return static_cast(key);
+ }
+
+
+
+
+
+ SIMD_FORCE_INLINE btBroadphasePair* internalFindPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, int hash)
+ {
+ int proxyId1 = proxy0->getUid();
+ int proxyId2 = proxy1->getUid();
+ #if 0 // wrong, 'equalsPair' use unsorted uids, copy-past devil striked again. Nat.
+ if (proxyId1 > proxyId2)
+ btSwap(proxyId1, proxyId2);
+ #endif
+
+ int index = m_hashTable[hash];
+
+ while( index != BT_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false)
+ {
+ index = m_next[index];
+ }
+
+ if ( index == BT_NULL_PAIR )
+ {
+ return NULL;
+ }
+
+ btAssert(index < m_overlappingPairArray.size());
+
+ return &m_overlappingPairArray[index];
+ }
+
+ virtual bool hasDeferredRemoval()
+ {
+ return false;
+ }
+
+ virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)
+ {
+ m_ghostPairCallback = ghostPairCallback;
+ }
+
+ virtual void sortOverlappingPairs(btDispatcher* dispatcher);
+
+
+
+};
+
+
+
+
+///btSortedOverlappingPairCache maintains the objects with overlapping AABB
+///Typically managed by the Broadphase, Axis3Sweep or btSimpleBroadphase
+class btSortedOverlappingPairCache : public btOverlappingPairCache
+{
+ protected:
+ //avoid brute-force finding all the time
+ btBroadphasePairArray m_overlappingPairArray;
+
+ //during the dispatch, check that user doesn't destroy/create proxy
+ bool m_blockedForChanges;
+
+ ///by default, do the removal during the pair traversal
+ bool m_hasDeferredRemoval;
+
+ //if set, use the callback instead of the built in filter in needBroadphaseCollision
+ btOverlapFilterCallback* m_overlapFilterCallback;
+
+ btOverlappingPairCallback* m_ghostPairCallback;
+
+ public:
+
+ btSortedOverlappingPairCache();
+ virtual ~btSortedOverlappingPairCache();
+
+ virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher);
+
+ void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher);
+
+ void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher);
+
+ btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
+
+ btBroadphasePair* findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
+
+
+ void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+
+ void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+
+
+ inline bool needsBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const
+ {
+ if (m_overlapFilterCallback)
+ return m_overlapFilterCallback->needBroadphaseCollision(proxy0,proxy1);
+
+ bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
+ collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
+
+ return collides;
+ }
+
+ btBroadphasePairArray& getOverlappingPairArray()
+ {
+ return m_overlappingPairArray;
+ }
+
+ const btBroadphasePairArray& getOverlappingPairArray() const
+ {
+ return m_overlappingPairArray;
+ }
+
+
+
+
+ btBroadphasePair* getOverlappingPairArrayPtr()
+ {
+ return &m_overlappingPairArray[0];
+ }
+
+ const btBroadphasePair* getOverlappingPairArrayPtr() const
+ {
+ return &m_overlappingPairArray[0];
+ }
+
+ int getNumOverlappingPairs() const
+ {
+ return m_overlappingPairArray.size();
+ }
+
+ btOverlapFilterCallback* getOverlapFilterCallback()
+ {
+ return m_overlapFilterCallback;
+ }
+
+ void setOverlapFilterCallback(btOverlapFilterCallback* callback)
+ {
+ m_overlapFilterCallback = callback;
+ }
+
+ virtual bool hasDeferredRemoval()
+ {
+ return m_hasDeferredRemoval;
+ }
+
+ virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)
+ {
+ m_ghostPairCallback = ghostPairCallback;
+ }
+
+ virtual void sortOverlappingPairs(btDispatcher* dispatcher);
+
+
+};
+
+
+
+///btNullPairCache skips add/removal of overlapping pairs. Userful for benchmarking and unit testing.
+class btNullPairCache : public btOverlappingPairCache
+{
+
+ btBroadphasePairArray m_overlappingPairArray;
+
+public:
+
+ virtual btBroadphasePair* getOverlappingPairArrayPtr()
+ {
+ return &m_overlappingPairArray[0];
+ }
+ const btBroadphasePair* getOverlappingPairArrayPtr() const
+ {
+ return &m_overlappingPairArray[0];
+ }
+ btBroadphasePairArray& getOverlappingPairArray()
+ {
+ return m_overlappingPairArray;
+ }
+
+ virtual void cleanOverlappingPair(btBroadphasePair& /*pair*/,btDispatcher* /*dispatcher*/)
+ {
+
+ }
+
+ virtual int getNumOverlappingPairs() const
+ {
+ return 0;
+ }
+
+ virtual void cleanProxyFromPairs(btBroadphaseProxy* /*proxy*/,btDispatcher* /*dispatcher*/)
+ {
+
+ }
+
+ virtual void setOverlapFilterCallback(btOverlapFilterCallback* /*callback*/)
+ {
+ }
+
+ virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* /*dispatcher*/)
+ {
+ }
+
+ virtual btBroadphasePair* findPair(btBroadphaseProxy* /*proxy0*/, btBroadphaseProxy* /*proxy1*/)
+ {
+ return 0;
+ }
+
+ virtual bool hasDeferredRemoval()
+ {
+ return true;
+ }
+
+ virtual void setInternalGhostPairCallback(btOverlappingPairCallback* /* ghostPairCallback */)
+ {
+
+ }
+
+ virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* /*proxy0*/,btBroadphaseProxy* /*proxy1*/)
+ {
+ return 0;
+ }
+
+ virtual void* removeOverlappingPair(btBroadphaseProxy* /*proxy0*/,btBroadphaseProxy* /*proxy1*/,btDispatcher* /*dispatcher*/)
+ {
+ return 0;
+ }
+
+ virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* /*proxy0*/,btDispatcher* /*dispatcher*/)
+ {
+ }
+
+ virtual void sortOverlappingPairs(btDispatcher* dispatcher)
+ {
+ (void) dispatcher;
+ }
+
+
+};
+
+
+#endif //BT_OVERLAPPING_PAIR_CACHE_H
+
+
diff --git a/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h
new file mode 100644
index 00000000..9c7b6f81
--- /dev/null
+++ b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h
@@ -0,0 +1,40 @@
+
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef OVERLAPPING_PAIR_CALLBACK_H
+#define OVERLAPPING_PAIR_CALLBACK_H
+
+class btDispatcher;
+struct btBroadphasePair;
+
+///The btOverlappingPairCallback class is an additional optional broadphase user callback for adding/removing overlapping pairs, similar interface to btOverlappingPairCache.
+class btOverlappingPairCallback
+{
+public:
+ virtual ~btOverlappingPairCallback()
+ {
+
+ }
+
+ virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) = 0;
+
+ virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher) = 0;
+
+ virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy0,btDispatcher* dispatcher) = 0;
+
+};
+
+#endif //OVERLAPPING_PAIR_CALLBACK_H
diff --git a/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp
new file mode 100644
index 00000000..889216df
--- /dev/null
+++ b/Code/Physics/Bullet Source/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp
@@ -0,0 +1,1393 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btQuantizedBvh.h"
+
+#include "LinearMath/btAabbUtil2.h"
+#include "LinearMath/btIDebugDraw.h"
+#include "LinearMath/btSerializer.h"
+
+#define RAYAABB2
+
+btQuantizedBvh::btQuantizedBvh() :
+ m_bulletVersion(BT_BULLET_VERSION),
+ m_useQuantization(false),
+ //m_traversalMode(TRAVERSAL_STACKLESS_CACHE_FRIENDLY)
+ m_traversalMode(TRAVERSAL_STACKLESS)
+ //m_traversalMode(TRAVERSAL_RECURSIVE)
+ ,m_subtreeHeaderCount(0) //PCK: add this line
+{
+ m_bvhAabbMin.setValue(-SIMD_INFINITY,-SIMD_INFINITY,-SIMD_INFINITY);
+ m_bvhAabbMax.setValue(SIMD_INFINITY,SIMD_INFINITY,SIMD_INFINITY);
+}
+
+
+
+
+
+void btQuantizedBvh::buildInternal()
+{
+ ///assumes that caller filled in the m_quantizedLeafNodes
+ m_useQuantization = true;
+ int numLeafNodes = 0;
+
+ if (m_useQuantization)
+ {
+ //now we have an array of leafnodes in m_leafNodes
+ numLeafNodes = m_quantizedLeafNodes.size();
+
+ m_quantizedContiguousNodes.resize(2*numLeafNodes);
+
+ }
+
+ m_curNodeIndex = 0;
+
+ buildTree(0,numLeafNodes);
+
+ ///if the entire tree is small then subtree size, we need to create a header info for the tree
+ if(m_useQuantization && !m_SubtreeHeaders.size())
+ {
+ btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
+ subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[0]);
+ subtree.m_rootNodeIndex = 0;
+ subtree.m_subtreeSize = m_quantizedContiguousNodes[0].isLeafNode() ? 1 : m_quantizedContiguousNodes[0].getEscapeIndex();
+ }
+
+ //PCK: update the copy of the size
+ m_subtreeHeaderCount = m_SubtreeHeaders.size();
+
+ //PCK: clear m_quantizedLeafNodes and m_leafNodes, they are temporary
+ m_quantizedLeafNodes.clear();
+ m_leafNodes.clear();
+}
+
+
+
+///just for debugging, to visualize the individual patches/subtrees
+#ifdef DEBUG_PATCH_COLORS
+btVector3 color[4]=
+{
+ btVector3(1,0,0),
+ btVector3(0,1,0),
+ btVector3(0,0,1),
+ btVector3(0,1,1)
+};
+#endif //DEBUG_PATCH_COLORS
+
+
+
+void btQuantizedBvh::setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin)
+{
+ //enlarge the AABB to avoid division by zero when initializing the quantization values
+ btVector3 clampValue(quantizationMargin,quantizationMargin,quantizationMargin);
+ m_bvhAabbMin = bvhAabbMin - clampValue;
+ m_bvhAabbMax = bvhAabbMax + clampValue;
+ btVector3 aabbSize = m_bvhAabbMax - m_bvhAabbMin;
+ m_bvhQuantization = btVector3(btScalar(65533.0),btScalar(65533.0),btScalar(65533.0)) / aabbSize;
+
+ m_useQuantization = true;
+
+ {
+ unsigned short vecIn[3];
+ btVector3 v;
+ {
+ quantize(vecIn,m_bvhAabbMin,false);
+ v = unQuantize(vecIn);
+ m_bvhAabbMin.setMin(v-clampValue);
+ }
+ {
+ quantize(vecIn,m_bvhAabbMax,true);
+ v = unQuantize(vecIn);
+ m_bvhAabbMax.setMax(v+clampValue);
+ }
+ aabbSize = m_bvhAabbMax - m_bvhAabbMin;
+ m_bvhQuantization = btVector3(btScalar(65533.0),btScalar(65533.0),btScalar(65533.0)) / aabbSize;
+ }
+}
+
+
+
+
+btQuantizedBvh::~btQuantizedBvh()
+{
+}
+
+#ifdef DEBUG_TREE_BUILDING
+int gStackDepth = 0;
+int gMaxStackDepth = 0;
+#endif //DEBUG_TREE_BUILDING
+
+void btQuantizedBvh::buildTree (int startIndex,int endIndex)
+{
+#ifdef DEBUG_TREE_BUILDING
+ gStackDepth++;
+ if (gStackDepth > gMaxStackDepth)
+ gMaxStackDepth = gStackDepth;
+#endif //DEBUG_TREE_BUILDING
+
+
+ int splitAxis, splitIndex, i;
+ int numIndices =endIndex-startIndex;
+ int curIndex = m_curNodeIndex;
+
+ btAssert(numIndices>0);
+
+ if (numIndices==1)
+ {
+#ifdef DEBUG_TREE_BUILDING
+ gStackDepth--;
+#endif //DEBUG_TREE_BUILDING
+
+ assignInternalNodeFromLeafNode(m_curNodeIndex,startIndex);
+
+ m_curNodeIndex++;
+ return;
+ }
+ //calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'.
+
+ splitAxis = calcSplittingAxis(startIndex,endIndex);
+
+ splitIndex = sortAndCalcSplittingIndex(startIndex,endIndex,splitAxis);
+
+ int internalNodeIndex = m_curNodeIndex;
+
+ //set the min aabb to 'inf' or a max value, and set the max aabb to a -inf/minimum value.
+ //the aabb will be expanded during buildTree/mergeInternalNodeAabb with actual node values
+ setInternalNodeAabbMin(m_curNodeIndex,m_bvhAabbMax);//can't use btVector3(SIMD_INFINITY,SIMD_INFINITY,SIMD_INFINITY)) because of quantization
+ setInternalNodeAabbMax(m_curNodeIndex,m_bvhAabbMin);//can't use btVector3(-SIMD_INFINITY,-SIMD_INFINITY,-SIMD_INFINITY)) because of quantization
+
+
+ for (i=startIndex;i